SQL WHERE: фильтры с AND, OR и NULL

Клауза SQL WHERE фильтрует строки таблицы по условию. В SQL-запросе со WHERE строка попадает в результат только тогда, когда предикат вычисляется в TRUE; результаты FALSE и NULL/UNKNOWN исключаются. Эта трехзначная логика чаще всего приводит к неожиданному поведению WHERE при работе с NULL.

Пример SQL WHERE Для Фильтрации Строк

Вывод:

Результат появится здесь...

Вывод:

+------------+-------------+-------+
| name       | category    | price |
+------------+-------------+-------+
| Клавиатура | Электроника | 49.99 |
| Мышь       | Электроника | 25.0  |
+------------+-------------+-------+
2 row(s)

Как Работает Этот Пример

  1. CREATE TABLE и INSERT создают таблицу products с четырьмя строками в двух категориях.
  2. В SQL-запросе клауза WHERE category = 'Электроника' AND price < 100 объединяет два условия через AND: оба должны быть TRUE, чтобы строка попала в результат.
  3. «Монитор» относится к категории «Электроника», но стоит 299.00, поэтому его отсекает условие по цене. «Блокнот» не проходит проверку категории. Оба предиката выполняются только для «Клавиатуры» и «Мыши».

Что Такое SQL WHERE?

Клауза SQL WHERE — это булев фильтр, который применяется к каждой строке отдельно. База данных вычисляет выражение для каждой подходящей строки и оставляет только те, где результат равен TRUE. Любое выражение с результатом FALSE или NULL отбрасывается. WHERE работает до GROUP BY и агрегатных функций, и этим отличается от HAVING.

Частые Ошибки В SQL WHERE

Ошибка: сравнивать столбец с NULL через =.

Неправильно:

WHERE category = NULL

Правильно:

WHERE category IS NULL

Почему это происходит: = NULL вычисляется в UNKNOWN, а WHERE отфильтровывает UNKNOWN-строки. Используйте IS NULL или IS NOT NULL.

Ошибка: смешивать AND и OR без скобок.

Неправильно:

WHERE category = 'Office' OR category = 'Electronics' AND price < 50

Правильно:

WHERE (category = 'Office' OR category = 'Electronics') AND price < 50

Почему это происходит: AND имеет более высокий приоритет, чем OR, поэтому без скобок выражение может работать не так, как задумано.

WHERE vs HAVING

WHEREHAVING
Фильтрует отдельные строки до группировкиФильтрует группы после агрегации
Не может ссылаться на агрегатные функцииМожет использовать COUNT, SUM и другие
Уменьшает число строк до GROUP BYУменьшает число групп в итоговом результате

Правило: используйте WHERE, чтобы исключать строки до агрегации, и HAVING, чтобы исключать группы после нее. Ранняя фильтрация через WHERE уменьшает объем работы на этапе агрегации.

Заметки О Производительности

Предикаты WHERE по индексированным столбцам превращают полное сканирование таблицы в индексный поиск. Если оборачивать столбец в функцию — LOWER(name), DATE(created_at) — оптимизатор обычно не сможет использовать индекс; преобразуйте значение для сравнения, а не столбец. Для условий, связанных AND, лучший результат обычно дает составной индекс в порядке столбцов предиката. Условия с OR часто выполняются как отдельные индексные сканирования с последующим объединением, что обычно медленнее, чем AND по тому же индексу.

Примечания По Безопасности

Формируйте условия WHERE через параметризованные запросы, а не через конкатенацию пользовательского ввода в SQL-строки. Для динамических имен столбцов проверяйте значения по строгому allow-list. Для списков IN (...) генерируйте плейсхолдеры и привязывайте каждое значение отдельно. Перед UPDATE и DELETE сначала выполните SELECT с тем же WHERE, чтобы проверить, какие строки попадут под изменение.

FAQ

В чем разница между WHERE и HAVING в SQL?

WHERE фильтрует строки до GROUP BY, а HAVING фильтрует агрегированные группы после него. WHERE не может ссылаться на агрегатные функции вроде COUNT() или SUM(). Один запрос может использовать оба: WHERE сужает входные строки, затем HAVING сужает сгруппированный результат.

Почему = NULL не работает в WHERE?

SQL использует трехзначную логику: TRUE, FALSE и UNKNOWN. Любое сравнение с NULL возвращает UNKNOWN, а WHERE отбрасывает UNKNOWN-строки. Для проверки NULL-значений используйте IS NULL. В некоторых СУБД также есть IS NOT DISTINCT FROM для NULL-безопасного сравнения на равенство.

Влияет ли порядок условий WHERE на производительность?

Стандарт SQL не гарантирует порядок вычисления, и большинство оптимизаторов переставляют предикаты внутри плана выполнения. Записывайте условия в порядке, который проще читать. Производительность зависит от того, какие столбцы индексированы и насколько селективен каждый предикат, а не от порядка записи условий.