2015-05-06 27 views
0

我有一個存儲管道以及日期和城市的表格。我需要按城市和安裝年份計算管道的長度總和和百分比。PostgreSQL窗口函數問題:詢問GROUP BY

下面是我在尋找的結果:

city | install_year | length | percentage 
---------+------------------+------------+--------------- 
    A  | 2014   | 90  | 32.14 
    A  | 2013   | 70  | 25.00 
    A  | 2012   | 120  | 42.85 
    B  | 2010   | 325  | 100.0 

我建立一個測試表,此腳本:

CREATE TABLE pipes (gid serial NOT NULL, city TEXT, install_year INTEGER, length INTEGER) ; 

INSERT INTO pipes (city, install_year, length) VALUES ('A',2014,10), ('A',2014,20), ('A',2014,60), ('A',2013,70), ('A',2012,120), ('B',2010,325) ; 

爲了實現我的查詢,我用一個窗口函數來計算管道「長度總和每個城鎮,如下:

SELECT 
    city, 
    install_year, 
    sum(length) AS length, 
    (sum(length)*100/sum(length) OVER (PARTITION BY city)) AS percentage 

FROM pipes 

GROUP BY city, install_year 

ORDER BY city, install_year DESC ; 

我得到一個錯誤信息,要求我加列‘長’到t他的GROUP BY子句,根本沒有給出相同的結果(我不想按長度分組,這是沒有意義的)。

任何人有一個想法做不同?恐怕我將不得不使用WITH mytable AS (...) SELECT ...的臨時表。

+0

'總和(長)* 100 /總和(長)'始終是100,這可能不是你想要的。 –

回答

1

窗口函數適用於group by之後,您應始終使用WINDOW關鍵字來記住這一點。

您已經很近了,您只需將總和按城市計算即可。

SELECT 
    city, 
    install_year, 
    sum(length) AS length, 
    sum(sum(length)) OVER w AS total_by_city, 
    (sum(length) * 100)/(sum(sum(length)) OVER w) AS percentage 
FROM pipes 
GROUP BY city, install_year 
WINDOW w AS (PARTITION BY city) 
ORDER BY city, install_year DESC; 
+0

非常感謝!在此期間我找到了另一種解決方案(請參閱下一個答案)。你能告訴我你對此的看法嗎? – wiltomap

+1

聰明的解決方案,但我認爲它效率稍低一些,因爲通過減少窗口函數需要處理的行數來使用組。完全取決於你的現實世界的行號,一羣可能會殺死表演。我發現你的解決方案有點難以理解,這種區別並不能幫助我們理解查詢在第一眼看到什麼,就像在我的解決方案中一樣,只有'百分比'需要更多的思考,而其餘的查詢非常簡單。 –

+0

好評,再次感謝。我保持你的! – wiltomap

0

我發現這一點:

SELECT DISTINCT 
    city, 
    install_year, 
    sum(length) OVER (PARTITION BY city, install_year) AS length, 
    sum(length) OVER (PARTITION BY city, install_year)*100/sum(length) OVER (PARTITION BY city) AS percentage 

FROM pipes 

ORDER BY city, install_year DESC ;