Перевести требование или бизнес-правило в SQL-проверку — «запрос должен вернуть ноль строк» или «доля не ниже порога» — и прочитать результат как подтверждение или нарушение требования.
Требование → утверждение → запрос
Запрос, который ищет нарушения
Требование превращается в утверждение о данных, а утверждение — в запрос, который ищет нарушения. Пустой результат значит, что на этих данных требование соблюдается (на этих — не навсегда). Непустой — список конкретных случаев для разбора.
Обязательность. «У доставленного заказа есть курьер и время доставки»:
SELECT order_id FROM orders
WHERE status = 'delivered'
AND (courier_id IS NULL OR delivered_at IS NULL)
Ожидание — 0 строк.
Уникальность. «У заказа не больше одной успешной оплаты»:
SELECT order_id, COUNT(*) FROM payments
WHERE status = 'succeeded'
GROUP BY order_id
HAVING COUNT(*) > 1
Нашлась хоть одна строка — это двойное списание и дефект.
Доля для НФТ. «Не меньше 90 % заказов доставляются за 60 минут»:
SELECT 100.0 * SUM(CASE WHEN delivery_minutes <= 60 THEN 1 ELSE 0 END) / COUNT(*)
FROM orders WHERE status = 'delivered'
CASE превращает условие в 1 или 0, а их сумма — число подходящих заказов (delivery_minutes в учебной базе считает сама база). 100.0, а не 100 — чтобы деление не стало целочисленным.
SQL не проверит то, чего нет в базе: время ответа и доступность API — в логах и мониторинге, понятность экрана — в исследовании с пользователями.
Типичные ошибки: «= NULL»; забытый фильтр по статусу (в долю попадут отменённые); условие на поле правой таблицы LEFT JOIN (p.status = 'succeeded') в WHERE вместо ON — строки без пары отсеются, соединение станет INNER. А вот IS NULL анти-соединения стоит именно в WHERE.
Шаблоны проверок
| Вид требования | Что ищет запрос | Ожидание |
|---|---|---|
| обязательность | строки с NULL в обязательном поле | 0 строк |
| уникальность | группы с COUNT(*) > 1 | 0 строк |
| связность | строки без пары через LEFT JOIN … IS NULL | 0 строк |
| жизненный цикл | доставленные заказы без успешной оплаты | 0 строк |
| доля | процент подходящих строк через CASE | не ниже порога |
Конспект урока
Запрос, который ищет нарушения
Требование превращается в утверждение о данных, а утверждение — в запрос, который ищет нарушения. Пустой результат значит, что на этих данных требование соблюдается (на этих — не навсегда). Непустой — список конкретных случаев для разбора.
Обязательность. «У доставленного заказа есть курьер и время доставки»:
SELECT order_id FROM orders
WHERE status = 'delivered'
AND (courier_id IS NULL OR delivered_at IS NULL)
Ожидание — 0 строк.
Уникальность. «У заказа не больше одной успешной оплаты»:
SELECT order_id, COUNT(*) FROM payments
WHERE status = 'succeeded'
GROUP BY order_id
HAVING COUNT(*) > 1
Нашлась хоть одна строка — это двойное списание и дефект.
Доля для НФТ. «Не меньше 90 % заказов доставляются за 60 минут»:
SELECT 100.0 * SUM(CASE WHEN delivery_minutes <= 60 THEN 1 ELSE 0 END) / COUNT(*)
FROM orders WHERE status = 'delivered'
CASE превращает условие в 1 или 0, а их сумма — число подходящих заказов (delivery_minutes в учебной базе считает сама база). 100.0, а не 100 — чтобы деление не стало целочисленным.
SQL не проверит то, чего нет в базе: время ответа и доступность API — в логах и мониторинге, понятность экрана — в исследовании с пользователями.
Типичные ошибки: «= NULL»; забытый фильтр по статусу (в долю попадут отменённые); условие на поле правой таблицы LEFT JOIN (p.status = 'succeeded') в WHERE вместо ON — строки без пары отсеются, соединение станет INNER. А вот IS NULL анти-соединения стоит именно в WHERE.