Структурируй запросы на именованные шаги с помощью WITH и связывай CTE в конвейер преобразований.
Открыть этот урок в KodokonПодзапрос, вложенный на три уровня, читается изнутри наружу: нечитаемо и невозможно вернуться к нему через полгода. CTE (Common Table Expression, клауза WITH) переворачивает порядок чтения: ты называешь каждый промежуточный шаг так же, как назвал бы функцию, и запрос читается сверху вниз. Загрузи этот набор данных в sqliteonline.com или sqlite3.
CREATE TABLE payments (
id INTEGER PRIMARY KEY,
customer TEXT NOT NULL,
paid_at TEXT NOT NULL,
amount REAL NOT NULL
);
INSERT INTO payments (customer, paid_at, amount)
VALUES
('alice', '2026-01-10', 120.0),
('bruno', '2026-01-22', 80.0),
('alice', '2026-02-05', 60.0),
('chloe', '2026-02-18', 200.0),
('bruno', '2026-03-03', 40.0),
('alice', '2026-03-15', 90.0),
('chloe', '2026-03-28', 150.0),
('bruno', '2026-04-09', 300.0);Базовый синтаксис: WITH name AS (SELECT ...), а следом основной запрос, который использует name как обычную таблицу. Здесь мы считаем месячную выручку, извлекая месяц из даты с помощью substr (даты в SQLite - это текст в формате ISO 8601, выбор движка, а не стандарта).
WITH monthly AS (
SELECT substr(paid_at, 1, 7) AS month,
SUM(amount) AS revenue
FROM payments
GROUP BY month
)
SELECT * FROM monthly ORDER BY month;Настоящая сила приходит с цепочкой: один WITH, несколько CTE через запятую, и каждый может читать те, что объявлены до него. Ты строишь конвейер: агрегировать, посчитать статистику, сравнить. Здесь мы ищем месяцы, чья выручка превышает среднюю по месяцам (ожидаем: 2026-03 и 2026-04, среднее равно 260).
WITH monthly AS (
SELECT substr(paid_at, 1, 7) AS month,
SUM(amount) AS revenue
FROM payments
GROUP BY month
),
stats AS (
SELECT AVG(revenue) AS avg_revenue
FROM monthly
)
SELECT m.month, m.revenue,
ROUND(s.avg_revenue, 1) AS avg_all
FROM monthly AS m
CROSS JOIN stats AS s
WHERE m.revenue > s.avg_revenue
ORDER BY m.month;