WHERE
WHERE фильтрует строки до группировки. В результат проходят только строки, для которых условие вычислилось в TRUE.
SELECT id, user_id, total
FROM orders
WHERE state = 'PAID'
AND total >= 1000.00;Трехзначная логика
В SQL есть TRUE, FALSE и UNKNOWN. Любое обычное сравнение с NULL дает UNKNOWN.
SELECT id
FROM users
WHERE status IS NULL;Ловушка:
-- Если подзапрос вернет хотя бы один NULL,
-- результат может оказаться пустым.
WHERE id NOT IN (SELECT user_id FROM blocked_users)Надежный вариант:
WHERE NOT EXISTS (
SELECT 1
FROM blocked_users AS b
WHERE b.user_id = users.id
)Условия, удобные для индекса
Выражение называют sargable, если СУБД может превратить его в диапазон поиска по индексу.
-- Индекс по created_at можно использовать как диапазон.
WHERE created_at >= TIMESTAMP '2026-07-01 00:00:00'
AND created_at < TIMESTAMP '2026-08-01 00:00:00'Менее удачный вариант:
WHERE EXTRACT(YEAR FROM created_at) = 2026Функция над столбцом часто мешает обычному индексу. Возможные решения: переписать условие диапазоном или создать функциональный индекс, если СУБД его поддерживает.
Приоритет операторов
AND обычно имеет более высокий приоритет, чем OR, но важное условие лучше выражать скобками:
WHERE state = 'PAID'
AND (total >= 1000 OR user_id = 7)Ловушки
WHERE total <> 0не включает строки сNULL.- Не добавляй
OR column IS NULLавтоматически: это меняет бизнес-смысл и план. - Параметры должны передаваться через prepared statement; конкатенация пользовательского ввода создает SQL injection.
- Фильтр по правой таблице в
WHEREможет превратитьLEFT JOINв фактическийINNER JOIN.
Связано: Операторы IS NULL BETWEEN IN, Оператор LIKE, Индексы SQL, Запрос из 2х таблиц.
Вопросы
Когда выполняется WHERE относительно GROUP BY? Логически до группировки.
Почему column = NULL не работает? Сравнение дает UNKNOWN; нужен IS NULL.
Чем опасна функция над индексированным столбцом? Она может сделать обычный индекс неприменимым для поиска.
Как безопасно подставлять значения? Через параметры prepared statement, а не склейку SQL-строки.