Как использовать оконную функцию SQL для вычисления процента от агрегата - PullRequest
14 голосов
/ 15 декабря 2011

Мне нужно рассчитать проценты различных измерений в таблице.Я хотел бы упростить вещи с помощью оконных функций для вычисления знаменателя, однако у меня возникла проблема, потому что числитель также должен быть агрегатом.1003 *

create temp table test (d1 text, d2 text, v numeric);
insert into test values ('a','x',5), ('a','y',5), ('a','y',10), ('b','x',20);

Если я просто хочу рассчитать долю каждой отдельной строки из d1, то оконные функции работают нормально:

select d1, d2, v/sum(v) over (partition by d1)
from test;

"b";"x";1.00
"a";"x";0.25
"a";"y";0.25
"a";"y";0.50

Однако мне нужно вычислить общееделить на сумму d2 из d1.Вывод, который я ищу:Я предполагаю, что это потому, что он жалуется на то, что оконная функция не учитывается в предложении группировки, однако оконные функции все равно не могут быть включены в предложение группировки.Postgresql 8.4 и имеет те же функции управления окнами.Обратите внимание, что Greenplum не может делать коррелированные подзапросы.

Ответы [ 2 ]

24 голосов
/ 15 декабря 2011

Я думаю, что вы на самом деле ищете это:

SELECT d1, d2, sum(v)/sum(sum(v)) OVER (PARTITION BY d1) AS share
FROM   test
GROUP  BY d1, d2;

Создает запрошенный результат.

Оконные функции применяются после агрегатных функций. Внешняя sum() в sum(sum(v)) в этом примере является оконной функцией и присоединяется к предложению OVER ..., а внутренняя sum() - совокупность.

Эффективно так же, как:

WITH x AS (
    SELECT d1, d2, sum(v) AS sv
    FROM   test
    GROUP  BY d1, d2
    )
SELECT d1, d2, sv/sum(sv) OVER (PARTITION BY d1) AS share
FROM   x;

Или (без CTE):

SELECT d1, d2, sv/sum(sv) OVER (PARTITION BY d1) AS share
FROM   (
    SELECT d1, d2, sum(v) AS sv
    FROM   test
    GROUP  BY d1, d2
    ) x;

Или вариант @ Му.

В сторону: Greenplum представил коррелированные подзапросы с версией 4.2. См. Примечания к выпуску.

2 голосов
/ 15 декабря 2011

Вам нужно сделать все это с помощью оконных функций? Похоже, вам просто нужно сгруппировать полученный результат по d1 и d2 и затем сложить суммы:

select d1, d2, sum(p)
from (
    select d1, d2, v/sum(v) over (partition by d1) as p
    from test
) as dt
group by d1, d2

Это дает мне это:

 d1 | d2 |          sum           
----+----+------------------------
 a  | x  | 0.25000000000000000000
 a  | y  | 0.75000000000000000000
 b  | x  | 1.00000000000000000000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...