Условные запросы в SQL – это применение предикатов в предложениях WHERE и HAVING для отбора строк и групп. Смысловой центр темы – логика предикатов над табличными данными: каждое условие для каждой строки вычисляется в одно из трёх логических значений (TRUE, FALSE, UNKNOWN), после чего СУБД решает, включать строку в результат или нет. Владение этой логикой обеспечивает уверенное решение экзаменационных задач: от простых фильтров до групповых условий и подзапросов.
Логическая основа SQL: трёхзначная логика
SQL использует трёхзначную логику: помимо TRUE и FALSE существует UNKNOWN (неизвестно), возникающее в первую очередь при участии NULL. Ключевые правила:
col = 5, если col IS NULL → результат UNKNOWN (не FALSE!).
В предложении WHERE остаются только строки, где предикат дал TRUE; строки с FALSE и UNKNOWN отбрасываются.
Логические связки:
TRUE AND UNKNOWN → UNKNOWN; FALSE AND UNKNOWN → FALSE.
TRUE OR UNKNOWN → TRUE; FALSE OR UNKNOWN → UNKNOWN.
NOT UNKNOWN → UNKNOWN.
Следствие: фильтр WHERE col <> 'X' не выбирает строки, где col IS NULL – они «выпадают» как UNKNOWN.
Базовый каркас запроса с условием:
SELECT список_полей
FROM таблица T
WHERE условие_над_строками
GROUP BY ...
HAVING условие_над_группами
ORDER BY ...
Приоритет операторов в WHERE (от высокого к низкому):
Сравнения
=, <> (или !=), <, <=, >, >=.
Типовое правило: совместимость типов. При сравнении строк учитывайте сортировку/коллацию
(регистрозависимость, правила сравнения). При сравнении чисел и дат исключайте неявные преобразования, т. к. они ухудшают производительность и могут менять смысл.
Специализированные предикаты
IS NULL / IS NOT NULL – единственный корректный способ проверять NULL.
BETWEEN a AND b – включительный интервал: a ≤ x ≤ b.
IN (…)/NOT IN (… ) – проверка вхождения в конечное множество. Опасность: NOT IN с подзапросом, содержащим NULL, даёт UNKNOWN и может «обнулить» результат.
LIKE – сопоставление с образцом: % – любой (в т. ч. пустой) префикс/суффикс, _ – ровно один символ. Экранирование спецсимволов – через ESCAPE.
EXISTS / NOT EXISTS – проверка наличия/отсутствия строк в подзапросе; устойчивы к NULL и рекомендуются вместо NOT IN для подзапросов.
Кванторы ANY/ALL (реже на ЕГЭ) – сравнение с любым/всеми значениями результата подзапроса.
Даты, строки, числа: точные правила
Даты/время. Избегайте функций над полем в WHERE (например, WHERE YEAR(dt)=2025) – это делает предикат несаргируемым (см. §6). Правильно задавать интервалы так: dt >= '2025-06-01' AND dt < '2025-07-01'.
Строки. Для регистронезависимого поиска лучше использовать соответствующую коллацию. Универсальный (но менее эффективный) приём – нормализовать обе стороны: WHERE UPPER(name) = UPPER('иван').
Числа. Следите за типами (INT, DECIMAL), избегайте сравнения чисел со строками.
WHERE, ON и HAVING: разграничение ответственности
WHERE – фильтр по строкам до группировки (GROUP BY) и до агрегирования.
ON – условие соединения таблиц при JOIN; влияет на набор пар для последующей фильтрации.
HAVING – фильтр по агрегированным результатам (после GROUP BY). Нельзя ссылаться на алиасы агрегатов в WHERE, но можно в HAVING.
Производительность и «саргируемость»
SARGable (Search ARGument able) – предикат, который СУБД может эффективно использовать с индексом. Правила:
Оставляйте индексируемое поле непреобразованным слева: плохо WHERE UPPER(col)=..., хорошо – выбирать регистронезависимую коллацию или нормализовать константу/ввод.
Предпочитайте диапазоны и равенства (=, BETWEEN, IN) над вычислениями в условии.
Избегайте LIKE '%...%' – ведущий % лишает использования индекса (если только не спец. индексы, типа полнотекстовых).

Чётко выпишите условие словами, определите поля и типы.
Переведите текст в предикат: расставьте AND/OR/NOT, проверьте приоритеты, добавьте скобки.
Учтите NULL: где нужны IS NULL/IS NOT NULL.
Для дат задайте полуинтервалы >= ... AND < ....
Разведите фильтры по уровням: строковые – в WHERE, агрегатные – в HAVING.
Проверьте «саргируемость» и корректность множества (не используйте NOT IN с потенциальным NULL в подзапросе).
= NULL или <> NULL – всегда неправильно. Нужны IS NULL / IS NOT NULL.
Неверная ассоциативность: забыли скобки при AND и OR → искажённое множество строк.
BETWEEN используется как полуинтервал – на самом деле он включительный.
NOT IN (подзапрос) с NULL → пустой результат. Заменяйте на NOT EXISTS.
Функции над полями в WHERE (несаргируемо) – при возможности перепишите.
Для примеров используем мини-схему (стилизовано под задания ЕГЭ):
Таблица Students:
id INT, name VARCHAR, class INT, city VARCHAR, birth DATE, score INT NULL
Таблица Enrollments:
student_id INT, course VARCHAR, grade INT NULL
Таблица Departments:
dept_id INT, dept_name VARCHAR
Таблица Employees:
emp_id INT, dept_id INT, salary INT
Упражнение 1. Приоритеты AND/OR/NOT и скобки
Задача. Выбрать учеников из Students, которые (а) из города «Тверь» и учатся в 10-м классе или (б) из города «Ярославль», но не в 9-м классе.
Правильная логика (со скобками):
SELECT id, name, class, city
FROM Students
WHERE (city = 'Тверь' AND class = 10)
OR (city = 'Ярославль' AND NOT (class = 9));
Почему важны скобки: без них AND имеет приоритет над OR, и выражение исказит условие (часть из «Ярославля» попадёт не так, как задумано).
Упражнение 2. NULL и ловушка NOT IN
Задача. Найти учеников, не записанных ни на один курс в Enrollments.
Неправильно (может вернуть 0 строк, если в Enrollments.student_id присутствует NULL):
SELECT s.id, s.name
FROM Students s
WHERE s.id NOT IN (SELECT e.student_id FROM Enrollments e);
Если подзапрос вернёт (..., NULL, ...), выражение x NOT IN (...) станет UNKNOWN и будет отброшено.
Правильно – через NOT EXISTS (устойчиво к NULL):
SELECT s.id, s.name
FROM Students s
WHERE NOT EXISTS (
SELECT 1
FROM Enrollments e
WHERE e.student_id = s.id
);
Комментарий для ЕГЭ: «нет соответствующих записей» почти всегда формулируется NOT EXISTS, а не NOT IN.
Упражнение 3. Датовые интервалы без ошибок включительности
Задача. Выбрать всех учеников, родившихся в июне 2008 года.
Правильно – полуинтервал:
SELECT id, name, birth
FROM Students
WHERE birth >= DATE '2008-06-01'
AND birth < DATE '2008-07-01';
Такой предикат:
учитывает всю июньскую часть (включая время, если тип – TIMESTAMP);
остаётся саргируемым (поле birth – слева без функций).
Почему не WHERE EXTRACT(MONTH FROM birth)=6? Это удобнее читать, но лишает индекс (несаргируемо) и может быть медленнее.
Упражнение 4. Сопоставление с образцом и экранирование
Задача. Выбрать учеников, чьи имена начинаются с «Ан» и затем имеют ровно один любой символ, после чего идёт «я» (например, «Антя», «Анфя»), а также тех, чьи имена буквально содержат символ подчёркивания _.
Решение 1 (ровно один символ – _):
SELECT id, name
FROM Students
WHERE name LIKE 'Ан_я';
Здесь _ – один любой символ. Примеры совпадений: «Аня» не пройдёт (нет символа между «Ан» и «я»), «Анья» – пройдёт.
Решение 2 (буквальный _ в имени – требуется ESCAPE):
SELECT id, name
FROM Students
WHERE name LIKE '%\_%' ESCAPE '\';
Здесь \ объявлен как символ экранирования; шаблон означает «содержит буквальный _». Без ESCAPE _ интерпретировался бы как «любой символ».
Упражнение 5. Разведение WHERE и HAVING при агрегировании
Задача. Для таблиц Employees(dept_id, salary) и Departments(dept_id, dept_name) вывести отделы, в которых не менее 5 сотрудников, а суммарная зарплата превышает 1 000 000. Отсечь из расчётов сотрудников с salary IS NULL.
Решение (фильтр NULL – в WHERE, агрегатные условия – в HAVING):
SELECT d.dept_name,
COUNT(e.emp_id) AS staff_cnt,
SUM(e.salary) AS total_pay
FROM Departments d
JOIN Employees e ON e.dept_id = d.dept_id
WHERE e.salary IS NOT NULL -- строковый фильтр ДО группировки
GROUP BY d.dept_name
HAVING COUNT(e.emp_id) >= 5 -- агрегатный фильтр ПОСЛЕ группировки
AND SUM(e.salary) > 1000000;
Пояснение: если перенести COUNT(...) или SUM(...) в WHERE, получите синтаксическую ошибку – агрегаты доступны только на стадии HAVING.
Условные запросы в SQL – это применение строгой предикатной логики к табличным данным с учётом трёхзначной семантики и правил вычисления предикатов. Для практики ЕГЭ важно:
знать различия WHERE/ON/HAVING;
уверенно оперировать AND/OR/NOT со скобками;
грамотно работать с NULL (IS NULL, NOT EXISTS);
корректно задавать интервал дат (полуинтервалы);
использовать LIKE и ESCAPE без двусмысленностей;
писать саргируемые условия, учитывающие индексы и типы.
Последовательно применяя эти правила и разобрав 5 упражнений, вы получаете устойчивый навык формализации текстовых условий в корректные и эффективные SQL-предикаты – именно это и проверяют экзаменационные задания.