GENERATE_SERIES в SQL — генерация календаря и числовых рядов

GENERATE_SERIES — функция, возвращающая набор строк: числовой ряд generate_series(1, 10) или календарь дат generate_series(start, stop, INTERVAL '1 day'). Главная польза для аналитика — построить непрерывный «скелет» дат и через LEFT JOIN закрыть дни без событий нулями, чтобы в графике не было провалов. Диалекты: это функция PostgreSQL; в SQLite есть табличная generate_series() только для чисел (и только если модуль скомпилирован), а в MySQL её нет — там используют рекурсивный CTE (WITH RECURSIVE).

Синтаксис

GENERATE_SERIES(start, stop) -- целые, шаг 1 GENERATE_SERIES(start, stop, step) -- целые с шагом GENERATE_SERIES(start_ts, stop_ts, interval) -- даты/время (PostgreSQL)

Примеры использования

Пример 1: Ряд чисел 1..5

SELECT generate_series(1, 5) AS n;

Результат:

n
--
1
2
3

Пример 2: Календарь дней месяца

SELECT generate_series(
         DATE '2026-07-01',
         DATE '2026-07-31',
         INTERVAL '1 day'
       )::date AS day;

Результат:

day
----------
2026-07-01
2026-07-02
2026-07-03

Пример 3: Заказы по дням без пропусков

SELECT d::date AS day,
       COUNT(o.id) AS orders
FROM generate_series(
       CURRENT_DATE - INTERVAL '6 days',
       CURRENT_DATE,
       INTERVAL '1 day'
     ) AS d
LEFT JOIN orders o
       ON o.created_at::date = d::date
GROUP BY 1
ORDER BY 1;

Результат:

day        | orders
-----------+-------
2026-07-05 | 12
2026-07-06 | 0
2026-07-07 | 19
Порешать SQL-задачи в тренажёре →

Типичная ошибка

Это set-returning функция — её ставят в FROM (или в SELECT), и для дат нужен явный шаг INTERVAL плюс часто приведение ::date. Если start больше stop при положительном шаге, вернётся 0 строк (легко получить пустой календарь). В SQLite generate_series только числовая и может быть не скомпилирована, в MySQL функции нет вовсе.

Где спрашивают на собеседовании

Спрашивают, когда нужно построить календарь/ось дат и заполнить пропущенные периоды; в паре с LEFT JOIN, DATE_TRUNC и агрегатами (COUNT/SUM).

FAQ: частые вопросы про GENERATE_SERIES

Есть ли GENERATE_SERIES в SQLite и MySQL?

В SQLite есть табличная функция generate_series(), но только для чисел и лишь если соответствующий модуль включён в сборку — версии для дат нет. В MySQL функции нет совсем: ряд строят рекурсивным CTE (WITH RECURSIVE dates AS (...)). Полноценно, включая даты, GENERATE_SERIES работает в PostgreSQL.

Как заполнить пропущенные дни нулями?

Сгенерируйте ряд дат через generate_series(start, stop, INTERVAL '1 day') и сделайте LEFT JOIN к таблице с данными по дате. Дни без записей дадут NULL, а COUNT(...) по ним вернёт 0. Так в отчёте не будет разрывов в оси времени.

Можно ли задать дробный или временной шаг?

Да. Для чисел работает дробный шаг: generate_series(0, 1, 0.25). Для времени шаг задаётся интервалом: generate_series(ts1, ts2, INTERVAL '1 hour') построит ряд по часам. Главное — знак шага должен вести от start к stop, иначе строк не будет.

Задачи в тренажёре по теме

Вопросы с собеседований по теме

Смежные темы SQL

Работа с датами · Агрегации

Другие функции SQL

LAG · date_trunc · EXTRACT · STRING_AGG · COUNT · SUM OVER

Открыть SQL-тренажёр (565 задач) →