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