Собесов

SQL — сумма операций за каждый день

SQLGROUP BY и агрегаты по датамЛёгкаяMiddle

Условие

В таблице task_3(date, amount) хранятся транзакции (date — дата/время, amount — сумма). Постройте SQL-запрос, возвращающий таблицу: дата + суммарная amount за этот день.

Решение

Подход

Если date уже типа DATE — простой GROUP BY date. Если это TIMESTAMP (есть время суток), нужно срезать до дня через DATE_TRUNC('day', date) (Postgres) или CAST(date AS DATE) / DATE(date) (MySQL).

В исходных данных задачи поле DATE приходит строкой формата m/d/yy — поэтому в эталонном ответе явно приводится к date::date.

Реализация

Эталон из ответов:

SELECT
  DATE_TRUNC('day', date::date) AS date,
  SUM(amount)                   AS day_sum
FROM task_3
GROUP BY DATE_TRUNC('day', date::date)
ORDER BY date;

Вариант для MySQL (без DATE_TRUNC):

SELECT
  DATE(STR_TO_DATE(`date`, '%c/%e/%y')) AS day,
  SUM(amount)                           AS day_sum
FROM task_3
GROUP BY DATE(STR_TO_DATE(`date`, '%c/%e/%y'))
ORDER BY day;

Вариант для ClickHouse:

SELECT
  toDate(date) AS day,
  SUM(amount)  AS day_sum
FROM task_3
GROUP BY day
ORDER BY day;

Подводные камни

  1. Тип date. Если значение хранится в строке ('6/1/21'), GROUP BY сгруппирует «как строку». На таких данных '6/1/21' и '06/01/21' будут разными группами. Всегда приводите к DATE явно.
  2. Часовой пояс. Для TIMESTAMP WITH TIME ZONE сначала конвертируйте в нужный TZ: DATE_TRUNC('day', ts AT TIME ZONE 'Europe/Moscow'). Иначе один реальный день может разбиться на два.
  3. Пропуски дней. Если за какой-то день транзакций не было — он не появится в результате. Если важна непрерывная серия (например, для графика), используйте LEFT JOIN к календарю-генератору (generate_series в Postgres).
  4. SELECT date_trunc(...) без алиаса в GROUP BY. В разных СУБД допустимо разное: Postgres понимает алиас в GROUP BY, ClickHouse — нет. Безопаснее повторять выражение в GROUP BY.

Эталонный ответ

SELECT DATE_TRUNC('day', date::date) AS date, SUM(amount) AS day_sum
FROM task_3
GROUP BY date;

В этой задаче это разогрев перед задачей 3.2 — там же надо посчитать ту же агрегацию накопительным итогом.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти