Условный оператор WHERE
Ситуация, когда требуется сделать выборку по определённому условию, встречается очень часто. Для этого в операторе SELECT существует оператор WHERE, после которого следуют условия для ограничения строк. Если запись удовлетворяет этому условию, то попадает в результат, иначе отбрасывается.
Общая структура запроса с оператором WHERE
SELECT [DISTINCT] поля_таблиц FROM наименование_таблицы WHERE условие_на_ограничение_строк [логический_оператор другое_условие_на_ограничение_строк];
Например, запрос с использованием оператора WHERE может выглядеть следующим образом:
SELECT * FROM Student WHERE first_name = "Grigorij" AND YEAR(birthday) > 2000;
SELECT * FROM Student WHERE first_name = 'Grigorij' AND EXTRACT(YEAR FROM birthday) > 2000;
В этом примере мы используем сразу два условия:
- first_name = "Grigorij" — имя студента должно быть «Grigorij»
- YEAR(birthday) > 2000 — год рождения больше 2000
- first_name = 'Grigorij' — имя студента должно быть «Grigorij»
- EXTRACT(YEAR FROM birthday) > 2000 — год рождения больше 2000
Между ними стоит логический оператор AND, который требует, чтобы оба условия выполнялись одновременно. В результате мы получаем только тех студентов, которые подходят под оба критерия.
Операторы сравнения
Чтобы сравнивать значения в SQL, используются специальные операторы. Они позволяют проверить, равны ли значения, больше ли одно другого, не равны ли они и так далее. Результатом сравнения может быть:
- true (это то же самое, что 1)
- false (то же, что 0)
- NULL (если результат сравнения не определён, например, при сравнении с NULL)
Результатом сравнения любого значения с NULL является NULL. Исключением является оператор эквивалентности.
Результатом сравнения любого значения с NULL является NULL.
Попробуйте сами поиграться с этими операторами в песочнице и посмотреть, какие результаты они дадут:
SELECT 2 = 1, 'a' = 'a', 1 <=> NULL, NULL <=> NULL, 2 <> 2, 3 < 4, 10 <= 10, 7 > 1, 8 >= 10;
SELECT 2 = 1, 'a' = 'a', 2 <> 2, 3 < 4, 10 <= 10, 7 > 1, 8 >= 10;
Логические операторы
Логические операторы — это ваши помощники, когда нужно объединить несколько условий в одном SQL-запросе. С их помощью вы можете гибко выбирать только те строки, которые вам действительно нужны. Давайте посмотрим как это работает на практике:
-
AND — оба условия должны быть верны.
Представьте, что вы ищете рейсы, которые одновременно соответствуют двум требованиям: например, самолёт должен быть определённой модели, и вылетать не из какого-то города. Оператор AND помогает объединить эти условия.
SELECT * FROM Trip WHERE plane = 'Boeing' AND town_from = 'London';
SELECT * FROM Trip WHERE plane = 'Boeing' AND town_from = 'London';
Такой запрос выберет только те рейсы, где модель самолёта — Boeing и город вылета — London.
Если хотя бы одно из условий не выполняется (например, самолёт не Boeing или вылет не из London), такой рейс не попадёт в результат.
-
OR — достаточно, чтобы выполнилось хотя бы одно условие.
Оператор OR работает как "или". Если хотя бы одно из условий верно — строка попадёт в результат. Это удобно, когда вы хотите увидеть все рейсы, которые соответствуют хотя бы одному из ваших критериев.
SELECT * FROM Trip WHERE town_to = 'Paris' OR plane = 'Airbus';
SELECT * FROM Trip WHERE town_to = 'Paris' OR plane = 'Airbus';
В результате вы получите все рейсы, которые прилетают в Paris, а также все рейсы на самолёте Airbus (даже если они летят не в Paris).
Если рейс и на Airbus, и в Paris — он тоже попадёт в результат.
-
NOT — условие становится противоположным.
Оператор NOT инвертирует условие: если оно было истинным, станет ложным, и наоборот. Это удобно, когда вы хотите исключить какие-то значения.
SELECT * FROM Trip WHERE NOT town_to = 'Moscow';
SELECT * FROM Trip WHERE NOT town_to = 'Moscow';
Такой запрос выберет все рейсы, которые прилетают не в Moscow.
То есть, если город прилёта — Moscow, такой рейс не попадёт в результат. Всё остальное — попадёт.
-
XOR — это оператор, который помогает выбрать строки, где выполняется только одно из двух условий, но не оба сразу.
Допустим, вы хотите найти рейсы, которые или вылетают из Moscow, или прилетают в Paris, но не оба варианта сразу. Давайте посмотрим на все возможные случаи:
SELECT * FROM trip WHERE town_from = 'Moscow' XOR town_to = 'Paris';
SELECT * FROM trip WHERE (town_from = 'Moscow' AND town_to != 'Paris') OR (town_from != 'Moscow' AND town_to = 'Paris');
Обратите внимание: оператор XOR есть не во всех базах данных. Если его нет, можно обойтись комбинацией AND и OR.
В PostgreSQL нет оператора XOR, поэтому используется комбинация AND и OR для достижения того же результата.
Приоритет логических операторов
Когда вы пишете запрос с несколькими условиями, SQL должен понять, в каком порядке их проверять. Это похоже на математику: сначала умножение, потом сложение. Для логических операторов в SQL тоже есть свой порядок — это называется приоритетом.
- Сначала — NOT
- Затем — AND
- Потом — XOR
- В конце — OR
Почему это важно?
Может показаться, что условия будут проверяться просто слева направо, но это не так! Если не учитывать порядок, можно получить неожиданный результат.
Посмотрим на такой пример:
SELECT * FROM Trip WHERE town_to = 'Paris' OR plane = 'Boeing' AND NOT town_from = 'Moscow';
SELECT * FROM Trip WHERE town_to = 'Paris' OR plane = 'Boeing' AND NOT town_from = 'Moscow';
Что здесь происходит:
-
Сначала проверяется, что рейс не из Moscow (NOT town_from = 'Moscow').
-
Затем смотрится, что самолёт — Boeing, и объединяется это с первым условием через AND, то есть, ищутся рейсы, которые не из Moscow и на Boeing (plane = 'Boeing' AND NOT town_from = 'Moscow')
-
Потом к результату добавляются все рейсы, которые прилетают в Paris, даже если они не на Boeing и вылетают из Moscow (town_to = 'Paris' OR ...).
В итоге получится следующая выборка:
- Все рейсы, которые не из Moscow и на Boeing
- А ещё все рейсы, которые прилетают в Paris
Если вы хотите изменить порядок проверки условий или сделать его более понятным, используйте скобки. Всё, что в скобках, выполняется в первую очередь. К примеру, если вручную расставить скобки согласно приоритетам логических операторов, то сразу становится понятно, как будет выполняться запрос!
SELECT * FROM Trip WHERE ( town_to = 'Paris' OR ( plane = 'Boeing' AND (NOT town_from = 'Moscow') ) );
SELECT * FROM Trip WHERE ( town_to = 'Paris' OR ( plane = 'Boeing' AND (NOT town_from = 'Moscow') ) );
А теперь попробуйте сами: допустим, вы хотите получить список рейсов, которые вылетают из Paris или на самолёте Boeing, и летят не в Moscow. Это можно сделать правильно расставив скобки в исходном запросе из примера. Как бы вы это сделали?