Перейти к основному содержимому

Оператор SELECT — синтаксис и стиль

Разработчику Аналитику Тестировщику Архитектору

Логическая структура SELECT

Текстовый порядок предложений в запросе не совпадает с порядком выполнения СУБД:

SELECT /* проекция: столбцы и выражения */
FROM /* источник: таблица, представление, подзапрос */
WHERE /* фильтрация строк до группировки */
GROUP BY /* группировка — при наличии агрегатов */
HAVING /* фильтрация групп */
ORDER BY /* сортировка результата */
LIMIT /* ограничение числа строк — PostgreSQL */

Логический порядок выполнения для простого запроса без группировки:

  1. FROM — формирование исходного множества строк;
  2. WHERE — отбор по предикату;
  3. SELECT — вычисление выражений и проекция столбцов;
  4. ORDER BY — сортировка;
  5. LIMIT / OFFSET — обрезка результата.

Псевдоним столбца из SELECT нельзя использовать в WHERE того же уровня — WHERE выполняется раньше проекции.

Подробная схема с JOIN, HAVING, оконными функциями: Принципы работы SQL-движка.

Загрузка SQL-тренажёра…

Проекция данных

-- Явный список столбцов (рекомендуется в прикладном коде)
SELECT product_id, name, price FROM products;

-- Все столбцы — только для отладки
SELECT * FROM products;

-- Вычисляемый столбец и псевдоним
SELECT name, price, price * 1.2 AS price_with_vat FROM products;

-- Уникальные значения столбца
SELECT DISTINCT category FROM products;

Фильтрация WHERE

КонструкцияНазначение
=, <>, <, <=, >, >=Сравнение
IS NULL, IS NOT NULLПроверка отсутствия значения
BETWEEN a AND bДиапазон включительно
IN (...)Принадлежность списку
LIKE 'шаблон'% — любая длина, _ — один символ
ILIKEРегистронезависимый поиск (PostgreSQL)
AND, OR, NOTПриоритет: NOT > AND > OR; скобки обязательны

Трёхзначная логика: сравнение с NULL через = или <> даёт UNKNOWN, а не TRUE/FALSE. Условие WHERE price = NULL не вернёт строк — используйте IS NULL / IS NOT NULL.

SELECT name, price
FROM products
WHERE category = 'Книги'
AND stock_qty > 0
AND price BETWEEN 300 AND 1000;

SELECT name FROM products WHERE name LIKE 'А%';

SELECT name, price, stock_qty
FROM products
WHERE (category = 'Аксессуары' AND price < 1000)
OR stock_qty = 0;

-- NULL: только IS NULL / IS NOT NULL
SELECT name, price FROM products WHERE price IS NULL;
SELECT name, price FROM products WHERE price IS NOT NULL;

Сортировка ORDER BY

SELECT name, price FROM products ORDER BY price DESC;

SELECT category, name, price
FROM products
ORDER BY category ASC, price DESC;

-- PostgreSQL: явная позиция NULL
SELECT name, stock_qty
FROM products
ORDER BY stock_qty NULLS LAST;

Сортировка по номеру столбца (ORDER BY 2) допустима, но снижает читаемость — предпочтительны имена.


Правила форматирования

  • Каждое предложение SELECT, FROM, WHERE, ORDER BY — с новой строки.
  • Список из более двух столбцов — по одному на строку.
  • Бинарные операторы окружают пробелами: price = 100, не price=100.
  • Сложные условия WHERE выравнивают по AND / OR.
  • Нетривиальные условия поясняют комментарием --.

Пример оформления:

SELECT
product_id,
name,
category,
price,
stock_qty
FROM products
WHERE
category IN ('Книги', 'Аксессуары')
AND price BETWEEN 100 AND 1500
AND stock_qty > 0
ORDER BY
category ASC,
price DESC;

Тестовые данные для практики

CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
sku VARCHAR(20) NOT NULL,
name TEXT NOT NULL,
category VARCHAR(30),
price NUMERIC(10, 2) NOT NULL,
stock_qty INTEGER NOT NULL DEFAULT 0,
created_at DATE NOT NULL
);

INSERT INTO products (sku, name, category, price, stock_qty, created_at) VALUES
('BOOK-001', 'Алгоритмы', 'Книги', 799.00, 15, '2023-01-15'),
('BOOK-002', 'SQL для профессионалов', 'Книги', 1299.00, 0, '2023-02-20'),
('GADGET-001', 'USB-кабель', 'Аксессуары', 299.00, 42, '2023-03-10'),
('GADGET-002', 'Power bank', 'Аксессуары', 1499.00, 8, '2023-03-12'),
('OFFICE-001', 'Блокнот', 'Канцелярия', 99.00, 120, '2023-01-30');

Контрольные вопросы

  1. Почему WHERE price = NULL не возвращает строк?
  2. В каком порядке СУБД выполняет FROM, WHERE и SELECT?
  3. Чем SELECT * отличается от явного списка столбцов при изменении схемы таблицы?
  4. Почему LIKE 'ABC%' может использовать индекс, а LIKE '%ABC' — обычно нет?

См. также


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).