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)
Как Работает Этот Пример
CREATE TABLEиINSERTсоздают таблицуproductsс четырьмя строками в двух категориях.- В SQL-запросе клауза WHERE
category = 'Электроника' AND price < 100объединяет два условия черезAND: оба должны быть TRUE, чтобы строка попала в результат. - «Монитор» относится к категории «Электроника», но стоит 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
| WHERE | HAVING |
|---|---|
| Фильтрует отдельные строки до группировки | Фильтрует группы после агрегации |
| Не может ссылаться на агрегатные функции | Может использовать 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 не гарантирует порядок вычисления, и большинство оптимизаторов переставляют предикаты внутри плана выполнения. Записывайте условия в порядке, который проще читать. Производительность зависит от того, какие столбцы индексированы и насколько селективен каждый предикат, а не от порядка записи условий.