#postgresql #group-by #rollup #postgresql-8.0
#postgresql #группировать по #свертка #postgresql-8.0
Вопрос:
Я пытаюсь выполнить свертку в postgresql 8.0. В последней версии postgresql у нас есть функция свертки, но как реализовать свертку в postgresql 8.0? У кого-нибудь есть опыт работы с таким же?
Я попробовал следующее
SELECT
EXTRACT (YEAR FROM rental_date) y,
EXTRACT (MONTH FROM rental_date) M,
EXTRACT (DAY FROM rental_date) d,
COUNT (rental_id)
FROM
rental
GROUP BY
ROLLUP (
EXTRACT (YEAR FROM rental_date),
EXTRACT (MONTH FROM rental_date),
EXTRACT (DAY FROM rental_date)
);
Но получаю следующую ошибку:
42883: function rollup( integer, integer, integer) does not exist
следует из http://www.postgresqltutorial.com/postgresql-rollup /
Комментарии:
1. Postgres 8.0 давно мертва и забыта. Для использования вам нужен как минимум Postgres 9.5 (выпущен через 11 лет после версии 8.0)
rollup
Ответ №1:
Как GROUP BY ROLLUP
было введено в версии 9.5, у запроса нет шансов сработать. Но если вы подумаете о том, что это делает, в вашем случае должно быть очень легко придумать версию, дающую тот же результат.
В принципе, вы хотите иметь:
- общая сумма
- сумма в год
- и сумма в месяц
- для ежедневных подсчетов
Я написал выше особым образом, чтобы стало ясно, что вам на самом деле нужно:
- производить ежедневные подсчеты
- генерировать сумму за месяц из ежедневных подсчетов
- генерировать сумму за год из ежемесячных сумм или ежедневных подсчетов
- генерировать итоговые данные из годовых сумм, месячных сумм или ежедневных подсчетов
UNION ALL
из вышеперечисленного в нужном порядке
Поскольку по умолчанию для GROUP BY ROLLUP
сначала записывается общее количество, а затем отдельные наборы группировок с NULLS LAST
, следующий запрос будет выполнять то же самое:
WITH
daily AS (
SELECT EXTRACT (YEAR FROM rental_date) y, EXTRACT (MONTH FROM rental_date) M, EXTRACT (DAY FROM rental_date) d, COUNT (rental_id) AS count
FROM rental
GROUP BY 1, 2, 3
),
monthly AS (
SELECT y, M, NULL::double precision d, SUM (count) AS count
FROM daily
GROUP BY 1, 2
),
yearly AS (
SELECT y, NULL::double precision M, NULL::double precision d, SUM (count) AS count
FROM monthly
GROUP BY 1
),
totals AS (
SELECT NULL::double precision y, NULL::double precision M, NULL::double precision d, SUM (count) AS count
FROM yearly
)
SELECT * FROM totals
UNION ALL
SELECT * FROM daily
UNION ALL
SELECT * FROM monthly
UNION ALL
SELECT * FROM yearly
;
Вышесказанное работает с PostgreSQL 8.4 . Если у вас даже нет этой версии, мы должны вернуться к старой школе UNION
без повторного использования данных агрегирования:
SELECT NULL::double precision y, NULL::double precision M, NULL::double precision d, COUNT (rental_id) AS count
FROM rental
UNION ALL
SELECT EXTRACT (YEAR FROM rental_date) y, EXTRACT (MONTH FROM rental_date) M, EXTRACT (DAY FROM rental_date) d, COUNT (rental_id) AS count
FROM rental
GROUP BY 1, 2, 3
UNION ALL
SELECT EXTRACT (YEAR FROM rental_date) y, EXTRACT (MONTH FROM rental_date) M, NULL::double precision d, COUNT (rental_id) AS count
FROM rental
GROUP BY 1, 2
UNION ALL
SELECT EXTRACT (YEAR FROM rental_date) y, NULL::double precision M, NULL::double precision d, COUNT (rental_id) AS count
FROM rental
GROUP BY 1
;
Комментарии:
1. общие табличные выражения (
with ...
) также не поддерживаются в Postgres 8.02. Я предполагал, что последняя версия в серии 8.x: postgresql.org/docs/8.4/sql-select.html но никаких проблем…