Фильтрация строк: WHERE и ловушка NULL
Курс MS SQL с нуля · Урок 3 из 12 · Часть 1. Среда и первые запросы
WHERE — самая нагруженная часть запроса на практике и главный источник логических ошибок у новичков. Урок разбирает сравнения, списки, шаблоны и трёхзначную логику NULL.
Перед уроком база обязана быть поднята скриптами урока 2; урок только читает данные и ничего не меняет.
Содержание
1. Что вы освоите
К концу урока вы:
- строите предикаты равенства, диапазона и принадлежности списку;
- ищете подстроки шаблонами LIKE с процентами и подчёркиваниями;
- объясняете трёхзначную логику NULL и пишете IS NULL корректно;
- доказываете полноту фильтра суммой обеих его половин;
- ставите скобки, когда рядом AND и OR.
2. Операторы сравнения и отрицание
Равенство пишется одиночным знаком «равно», диапазоны — через BETWEEN; замысел «не равно» выражается отрицанием равенства:
Чистый код
WHERE Price BETWEEN 1000 AND 2000
WHERE Status = N'Paid'
WHERE NOT (Status = N'Cancelled')
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
WHERE Price BETWEEN 1000 AND 2000 -- → диапазон от тысячи до двух тысяч, обе границы включаются WHERE Status = N'Paid' -- → равенство одиночным знаком «равно», литерал с префиксом N WHERE NOT (Status = N'Cancelled') -- → каноничное отрицание курса: NOT плюс равенство в скобкахSQL
Списки и шаблоны
IN проверяет принадлежность списку, LIKE — шаблону: процент — любое число любых символов, подчёркивание — ровно один символ:
Чистый код
WHERE Status IN (N'New', N'Paid')
WHERE SKU LIKE N'SKU-00___'
WHERE Attributes LIKE N'%black%'
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
WHERE Status IN (N'New', N'Paid') -- → принадлежность списку: равно хотя бы одному из значений WHERE SKU LIKE N'SKU-00___' -- → пять подчёркиваний: ровно пять любых знаков на хвосте артикула WHERE Attributes LIKE N'%black%' -- → проценты с обеих сторон: слово встречается в любом месте строкиSQL
3. Ловушка NULL и приём полноты
NULL — «значения нет», а не ноль и не пустая строка. Любое сравнение с NULL даёт НЕИЗВЕСТНО, а WHERE пропускает строку только при ИСТИНА. Следствия:
WHERE Email = NULLне вернёт ничего никогда; правильно — IS NULL и IS NOT NULL;WHERE NOT (Segment = N'VIP')теряет строки, где Segment IS NULL: если NULL-строки нужны, добавляют OR Segment IS NULL;- проверка фильтра: сумма половин «выполняется» и «не выполняется» обязана равняться всей таблице.
Приём полноты
универсальная диагностика фильтров
Чистый код
SELECT COUNT(*) FROM dbo.Products WHERE Attributes IS NULL;
SELECT COUNT(*) FROM dbo.Products WHERE Attributes IS NOT NULL;
SELECT COUNT(*) FROM dbo.Products;
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
SELECT COUNT(*) FROM dbo.Products WHERE Attributes IS NULL; -- → половина А: сколько товаров без атрибутов SELECT COUNT(*) FROM dbo.Products WHERE Attributes IS NOT NULL; -- → половина Б: сколько с атрибутами SELECT COUNT(*) FROM dbo.Products; -- → целое, ровно 500; фильтр исправен, если А плюс Б равно 500полнота: А + Б = 500
4. Приоритет AND и OR
AND связывает сильнее OR. Условие «активные товары дешевле тысячи или из категории 5» без скобок читается сервером как «(активные и дешёвые) или (категория)» — это другая выборка:
Чистый код
WHERE IsActive = 1 AND Price BETWEEN 0 AND 999 OR CategoryID = 5
WHERE (IsActive = 1 AND Price BETWEEN 0 AND 999) OR CategoryID = 5
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
WHERE IsActive = 1 AND Price BETWEEN 0 AND 999 OR CategoryID = 5 -- → антипример: сервер читает как (активные и дешёвые) или (категория 5) WHERE (IsActive = 1 AND Price BETWEEN 0 AND 999) OR CategoryID = 5 -- → эталон: скобки фиксируют, что условие по категории — отдельная веткаSQL
Даты как диапазоны
OrderDate — DATETIME2: кроме даты там время. Фильтр «за один день» пишется включительным диапазоном от полуночи до последней секунды дня:
Чистый код
WHERE OrderDate BETWEEN '2026-10-23 00:00:00' AND '2026-10-23 23:59:59'
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
WHERE OrderDate BETWEEN '2026-10-23 00:00:00' AND '2026-10-23 23:59:59' -- → весь день: от полуночи до последней секунды; DATETIME2 хранит и времяSQL
5. Задачи и эталонные решения
Семь задач на контексте TechStore.
- товары с ценой от тысячи до двух тысяч включительно, дешёвые сначала;
- заказы в статусах New, Paid и Shipped одним IN без цепочки OR;
- товары, в JSON-атрибутах которых встречается слово black;
- все клиенты с общими адресами вида
Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. — шаблон с якорем; - полнота фильтра Attributes: NULL, NOT NULL и их сумма против всей таблицы;
- все заказы самого свежего дня данных: дата берётся из MAX(OrderDate);
- вариант условия «активные и дешёвые или категория 5» без скобок и со скобками: разница и объяснение.
Эталоны урока
открывать после самостоятельной попытки
Чистый код
SELECT ProductID, Name, Price
FROM dbo.Products
WHERE Price BETWEEN 1000 AND 2000
ORDER BY Price;
GO
SELECT OrderID, OrderDate, Status
FROM dbo.Orders
WHERE Status IN (N'New', N'Paid', N'Shipped');
GO
SELECT ProductID, Name, Attributes
FROM dbo.Products
WHERE Attributes LIKE N'%black%'
ORDER BY Name;
GO
SELECT CustomerID, FullName, Email
FROM dbo.Customers
WHERE Email LIKE N'shared%@example.com';
GO
SELECT MAX(OrderDate) AS last_order_at FROM dbo.Orders;
GO
SELECT OrderID, OrderDate, Status, TotalAmount
FROM dbo.Orders
WHERE OrderDate BETWEEN '2026-10-23 00:00:00' AND '2026-10-23 23:59:59'
ORDER BY OrderDate;
GO
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
SELECT ProductID, Name, Price -- → задача 3.1: диапазон цен с включительными границами FROM dbo.Products WHERE Price BETWEEN 1000 AND 2000 ORDER BY Price; -- → дешёвые сначала GO SELECT OrderID, OrderDate, Status -- → задача 3.2: три статуса одним IN, без цепочки OR FROM dbo.Orders WHERE Status IN (N'New', N'Paid', N'Shipped'); GO SELECT ProductID, Name, Attributes -- → задача 3.3: подстрока в атрибутах; строки с NULL молча отсекаются LIKE FROM dbo.Products WHERE Attributes LIKE N'%black%' ORDER BY Name; GO SELECT CustomerID, FullName, Email -- → задача 3.4: якорь слева от домена, чтобы не поймать лишнее FROM dbo.Customers WHERE Email LIKE N'shared%@example.com'; GO SELECT MAX(OrderDate) AS last_order_at FROM dbo.Orders; -- → задача 3.6, первый приём: отдельный запрос узнаёт самую свежую дату GO SELECT OrderID, OrderDate, Status, TotalAmount -- → задача 3.6, второй приём: весь найденный день одним диапазоном FROM dbo.Orders WHERE OrderDate BETWEEN '2026-10-23 00:00:00' AND '2026-10-23 23:59:59' ORDER BY OrderDate; -- → дата подставлена из предыдущего результата GOрешения задач 3.1–3.4 и 3.6
6. Типичные ошибки урока
- Равно NULL вместо IS NULL — ошибки нет, результат пустой; диагностика счётчиками обеих половин.
- Кириллический литерал без N — возможен пустой результат; столбцы базы NVARCHAR, N-литералы пишутся всегда.
- Шаблон без якоря — %shared% способен поймать лишнее с той же подстрокой; якорь слева: shared%@example.com.
- Потерянный конец дня — BETWEEN до голой даты при DATETIME2 ловит дату лишь на момент полуночи.
- NOT при NULL в столбце — строки молча теряются; проверка — приём полноты задачи 3.5.
- Работает одно условие из двух — пропущены скобки вокруг OR; ветки гоняются по отдельности и сравниваются числами строк.
7. Чек-лист практики и источники
Чек-лист урока 3
отметки делаются по факту
Источники для углубления:
- Предложение WHERE: синтаксис и примеры;
- LIKE: символы шаблона;
- IS NULL: проверки на неопределённость.
Проверено: 23.10.2026
↑ К оглавлению