Группировка строк по неделям в Postgresql: решение
Быстрый ответ
Для реализации группировки записей по неделям в PostgreSQL следует использовать функцию date_trunc
с параметром 'week'
. Это позволит группировать записи с начала каждой недели, исходя из понедельника. Пример своего рода запроса:
SELECT
date_trunc('week', your_date_column) as week_start,
COUNT(*)
FROM
your_table
GROUP BY
1
ORDER BY
1;
Подставьте вместо your_date_column
название поля с датами в вашей таблице и вместо your_table
— название вашей таблицы. Запрос выполнит подсчёт записей, сгруппированных по началу каждой недели.
Учет данных за несколько лет
Если ваши данные охватывают несколько лет, то при группировке следует учитывать год, чтобы избежать путаницы с номерами недель из разных лет:
SELECT
date_part('year', author_date::date) as year,
date_trunc('week', author_date::date) as week_start,
COUNT(author_email) as commit_count
FROM
your_table
GROUP BY
1, 2
ORDER BY
1, 2;
В данном случае вместо author_date
следует подставить поле с датами, а вместо your_table
– имя вашей таблицы. В итоге данные будут сгруппированы по неделям с учетом года.
Доскональный анализ недельных данных
Чтобы удостовериться, что все недели учтены, включая те, по которым отсутствуют данные, создайте последовательность недель и соедините ее с исходными данными:
WITH weekly_series AS (
SELECT generate_series(
MIN(date_trunc('week', author_date))::DATE,
MAX(author_date)::DATE,
'1 week'::INTERVAL
) as week_start
FROM your_table
)
SELECT
w.week_start,
To_char(w.week_start, 'YYYY-WW') AS formatted_week,
COALESCE(COUNT(yt.author_email), 0) AS commit_count
FROM
weekly_series w
LEFT OUTER JOIN
your_table yt
ON
date_trunc('week', yt.author_date) = w.week_start
GROUP BY
w.week_start
ORDER BY
w.week_start;
Функция generate_series
создаёт последовательность недель, а LEFT OUTER JOIN гарантирует, что все недели будут представлены в финальном отчёте, несмотря на отсутствие данных по некоторым из них.
Визуализация
Если дать сравнение, то можно представить процесс как распределение книг по полкам в библиотеке в течение недели:
Полка 1 (Неделя 1): [Пн 📕, Вт 📗, Ср 📘, Чт 📙, Пт 📔, Сб 📒, Вс 📓]
Полка 2 (Неделя 2): [Пн 📕, Вт 📗, Ср 📘, ...]
// и так далее...
Получается, что вы, как библиотекарь, определяете, к какой неделе относится каждая книга, ориентируясь на календарь.
SELECT
date_trunc('week', issue_date) AS week_start,
COUNT(*) AS books_issued
FROM library_data
GROUP BY week_start;
Поэтому, GROUP BY
помогает систематизировать книги по неделям, распределяя их по соответствующим полкам.
Сглаживание неравномерности в данных
Если ваши данные распределены неравномерно и имеются недели без активности, то понадобится таблица календаря или ряд чисел для компенсации этого:
WITH calendar AS (
SELECT generate_series('2023-01-01'::DATE, '2023-12-31'::DATE, '1 week') AS week_start
)
SELECT
c.week_start,
COUNT(yt.your_date_column)
FROM
calendar c
LEFT JOIN
your_table yt
ON
date_trunc('week', yt.your_date_column) = c.week_start
GROUP BY
c.week_start
ORDER BY
c.week_start;
Замените даты в generate_series
на тот период, за который нужно подготовить отчёт, чтобы обеспечить полноту данных, вне зависимости от их первоначального распределения.
Вывод данных в удобночитаемом формате
Функция To_char
полезна для повышения читаемости недельных отчётов:
SELECT
To_char(date_trunc('week', author_date)::date, 'IYYY-IW') as formatted_week,
COUNT(author_email)
FROM
your_table
GROUP BY
formatted_week
ORDER BY
formatted_week;
Это позволяет отформатировать отчёты в соответствии со стандартом ISO 8601 (например, 2023-W09
), что делает анализ периода более очевидным и облегчает общение.
Полезные материалы
- PostgreSQL: Документация: Функции и операторы работы с датой и временем — официальная документация PostgreSQL.
- Не делайте так – PostgreSQL wiki — обзор распространенных ошибок при работе с датой и временем.
- Postgres Weekly 319: 21 августа 2019 — новостной дайджест по PostgreSQL, включая информацию и по временным данным.
- Database Journal: Группировка по временным интервалам в PostgreSQL — публикация с практическими советами о группировке данных во временных интервалах.