Свернуть иерархию данных в postgresql 8.0? - PullRequest
0 голосов
/ 08 апреля 2019

Я пытаюсь накопить в postgresql 8.0.В последней версии postgresql у нас есть функция ROLLUP, но как реализовать накопительный пакет в 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 Ответ

0 голосов
/ 08 апреля 2019

Поскольку GROUP BY ROLLUP был представлен с версией 9.5 , запрос не имеет шансов работать. Но если вы думаете о том, что он делает, в вашем случае будет очень легко придумать версию с таким же результатом.

Как правило, вы хотите иметь:

  1. общая сумма
  2. сумма в год
  3. и сумма в месяц
  4. для ежедневных подсчетов

Я специально написал вышеупомянутое, чтобы стало ясно, что вам действительно нужно:

  1. производить ежедневные подсчеты
  2. генерирует сумму в месяц из ежедневных подсчетов
  3. генерирует сумму в год из сумм за месяц или по дням
  4. генерировать итоговую сумму из годовых сумм, месячных сумм или ежедневных подсчетов
  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
;
...