11

Tôi cần tính phần trăm các thứ nguyên khác nhau trong bảng. Tôi muốn đơn giản hóa mọi thứ bằng cách sử dụng các hàm cửa sổ để tính toán mẫu số, tuy nhiên tôi đang gặp vấn đề bởi vì tử số cũng phải là tổng hợp.Cách sử dụng hàm cửa sổ SQL để tính phần trăm của tổng hợp

Như một ví dụ đơn giản, hãy bảng sau:

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); 

Nếu tôi chỉ muốn để tính toán tỷ lệ mỗi hàng cá nhân ra khỏi d1, chức năng sau đó windowing hoạt động tốt:

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 

Tuy nhiên, những gì tôi cần làm là tính toán tỷ lệ chung cho tổng của d2 trong số d1. Sản lượng Tôi đang tìm kiếm là thế này:

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

Vì vậy, tôi cố gắng này:

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

Tuy nhiên, bây giờ tôi nhận được một lỗi:

ERROR: column "test.v" must appear in the GROUP BY clause or be used in an aggregate function 

Tôi giả định này là vì nó phàn nàn rằng chức năng cửa sổ không được tính trong mệnh đề nhóm, tuy nhiên các chức năng cửa sổ không thể được đặt trong mệnh đề nhóm.

Điều này đang sử dụng Greenplum 4.1, là một nhánh của Postgresql 8.4 và chia sẻ cùng một chức năng cửa sổ. Lưu ý rằng Greenplum không thể thực hiện các truy vấn con tương quan.

Trả lời

16

Tôi nghĩ rằng những gì bạn đang thực sự tìm kiếm là đây :

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

Tạo kết quả được yêu cầu.

Chức năng cửa sổ được áp dụng sau chức năng tổng hợp. Bên ngoài sum() trong sum(sum(v)) là chức năng cửa sổ trong ví dụ này và được đính kèm với mệnh đề OVER ..., trong khi bên trong sum() là tổng hợp.

có hiệu quả tương tự như:

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; 

Hoặc (không 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; 

Hoặc @ biến Mu.

Bên cạnh: Greenplum đã giới thiệu các truy vấn phụ có liên quan với phiên bản 4.2. See release notes.

+0

Ah tuyệt vời! Đó là những gì tôi đã sau. Có ý nghĩa. Các tài liệu không phải là tất cả những gì rõ ràng về công cụ này. – EvilPuppetMaster

+0

@erwinBrandsletter Đã cứu mạng tôi! cảm ơn – isJustMe

1

Bạn có cần làm tất cả với chức năng cửa sổ không? Âm thanh như bạn chỉ cần vào nhóm kết quả bạn có bằng d1d2 và sau đó tổng số tiền:

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 

Đó mang lại cho tôi điều này:

d1 | d2 |   sum   
----+----+------------------------ 
a | x | 0.25000000000000000000 
a | y | 0.75000000000000000000 
b | x | 1.00000000000000000000 
+1

Ah đúng, điều đó thực sự hiệu quả. Lý do tôi muốn làm điều đó mà không có một truy vấn phụ mặc dù là bởi vì điều này thực sự cần phải đi vào một công cụ BI (Tableau), và truy vấn phụ gây ra vấn đề. – EvilPuppetMaster

Các vấn đề liên quan