SELECT — первая команда, которую учит каждый, кто начинает работать с SQL. Но за простым синтаксисом скрываются десятки нюансов. В этой статье — полный разбор от простого к сложному.
Что делает SELECT
SELECT читает данные из таблицы (или нескольких). Это единственная команда чтения в SQL — она не изменяет данные.
SELECT column1, column2
FROM table_name;
Самый простой запрос — получить все столбцы:
SELECT * FROM products;
* означает «все столбцы». На практике лучше перечислять нужные явно — это ускоряет запрос и делает код понятнее.
Пример: таблица products
Допустим, у нас есть таблица товаров:
| id | name | category | price | stock |
|---|---|---|---|---|
| 1 | Ноутбук | Электроника | 85000 | 15 |
| 2 | Мышь | Электроника | 1500 | 200 |
| 3 | Стол | Мебель | 12000 | 8 |
| 4 | Кресло | Мебель | 25000 | 3 |
| 5 | Наушники | Электроника | 8000 | 0 |
WHERE — фильтрация строк
WHERE отбирает строки по условию:
SELECT name, price
FROM products
WHERE category = 'Электроника';
Результат: ноутбук, мышь, наушники.
Операторы сравнения
| Оператор | Значение |
|---|---|
= | Равно |
<> или != | Не равно |
> | Больше |
< | Меньше |
>= | Больше или равно |
<= | Меньше или равно |
-- Товары дороже 10 000
SELECT name, price FROM products WHERE price > 10000;
-- Товары в наличии
SELECT name, stock FROM products WHERE stock > 0;
AND, OR, NOT
-- Электроника дешевле 10 000
SELECT name, price
FROM products
WHERE category = 'Электроника' AND price < 10000;
-- Мебель или товары без остатка
SELECT name, category, stock
FROM products
WHERE category = 'Мебель' OR stock = 0;
Порядок приоритетов: NOT > AND > OR. Используйте скобки для ясности:
-- Без скобок — неожиданный результат
WHERE category = 'Электроника' OR stock = 0 AND price > 5000
-- Это читается как:
WHERE category = 'Электроника' OR (stock = 0 AND price > 5000)
BETWEEN — диапазон
SELECT name, price
FROM products
WHERE price BETWEEN 1000 AND 20000;
-- Включает границы (1000 и 20000)
IN — список значений
SELECT name FROM products
WHERE category IN ('Электроника', 'Мебель');
-- Обратное: не входит в список
SELECT name FROM products
WHERE category NOT IN ('Мебель');
LIKE — поиск по шаблону
-- Имя начинается с 'Н'
SELECT name FROM products WHERE name LIKE 'Н%';
-- Содержит 'ноут' (без учёта регистра — ILIKE в PostgreSQL)
SELECT name FROM products WHERE name ILIKE '%ноут%';
% — любое количество символов, _ — ровно один символ.
ORDER BY — сортировка
SELECT name, price
FROM products
ORDER BY price DESC;
-- ASC — по возрастанию (по умолчанию), DESC — по убыванию
Сортировка по нескольким полям:
SELECT name, category, price
FROM products
ORDER BY category ASC, price DESC;
-- Сначала сортируем по категории, внутри категории — по цене (дороже первые)
LIMIT и OFFSET — пагинация
-- Первые 3 товара
SELECT name, price FROM products ORDER BY price DESC LIMIT 3;
-- Пропустить первые 3, взять следующие 3 (страница 2)
SELECT name, price FROM products ORDER BY price DESC LIMIT 3 OFFSET 3;
⚠️ OFFSET медленнее при больших смещениях: PostgreSQL всё равно читает пропущенные строки. Для глубокой пагинации используйте курсорный метод (WHERE id > last_seen_id).
Алиасы — AS
Позволяют переименовать столбец или таблицу в результате:
SELECT
name AS product_name,
price AS price_rub,
price * 0.012 AS price_usd
FROM products;
AS можно опустить:
SELECT name product_name, price price_rub FROM products;
Но с AS читается яснее — оставляйте его.
DISTINCT — уникальные значения
Убирает дубликаты из результата:
SELECT DISTINCT category FROM products;
-- Вернёт: Электроника, Мебель
Выражения в SELECT
В SELECT можно вычислять:
SELECT
name,
price,
stock,
price * stock AS total_value, -- арифметика
UPPER(name) AS name_upper, -- строковая функция
ROUND(price * 0.012, 2) AS usd -- округление
FROM products;
Порядок выполнения SQL-запроса
Запрос читается слева направо, но выполняется в другом порядке:
1. FROM — какая таблица
2. WHERE — фильтр строк
3. GROUP BY — группировка
4. HAVING — фильтр групп
5. SELECT — выбираем столбцы
6. ORDER BY — сортировка
7. LIMIT — ограничение
Это объясняет, почему нельзя использовать алиас из SELECT в WHERE:
-- Ошибка! price_usd ещё не существует на этапе WHERE
SELECT price * 0.012 AS price_usd
FROM products
WHERE price_usd < 100;
-- Правильно:
SELECT price * 0.012 AS price_usd
FROM products
WHERE price * 0.012 < 100;
NULL в WHERE
NULL — особое значение «неизвестно». Сравнение с = не работает:
-- Не найдёт строки с NULL!
SELECT * FROM products WHERE description = NULL;
-- Правильно:
SELECT * FROM products WHERE description IS NULL;
SELECT * FROM products WHERE description IS NOT NULL;
Частые ошибки
1. SELECT * в продакшне — тянет лишние данные, ломается при изменении схемы.
2. OR без скобок — нарушает ожидаемую логику.
3. LIKE '%текст%' без индекса — полное сканирование таблицы. Для поиска по тексту используйте полнотекстовый поиск.
4. OFFSET 10000 — очень медленно. Используйте курсорный метод.
Итог
| Конструкция | Что делает |
|---|---|
SELECT col | Выбирает столбцы |
FROM table | Источник данных |
WHERE cond | Фильтр строк |
ORDER BY col DESC | Сортировка |
LIMIT n OFFSET m | Пагинация |
AS alias | Переименование |
DISTINCT | Убирает дубликаты |
Это фундамент SQL. На основе SELECT строятся JOIN, подзапросы, агрегации и оконные функции — обо всём этом читайте в других статьях блога.