Postgresql
如何在 PostgreSQL 9.5 中旋轉多個列?
我有如下範例數據,想看看在這種情況下是否可以使用交叉表函式。
樣本數據:
ITEM | CD | TYPE |PARTS | PART | CNT | Item 1 | A | AVG |2 | 1 | 10 | Item 1 | A | AVG |2 | 2 | 20 | Item 1 | B | AVG |2 | 1 | 10 | Item 1 | B | AVG |2 | 2 | 20 | Item 1 | A | SUM |2 | 1 | 10 | Item 1 | A | SUM |2 | 2 | 20 | Item 1 | B | SUM |2 | 1 | 10 | Item 1 | B | SUM |2 | 2 | 20 |
預期結果:
ITEM | CD | AVG_1 | SUM_1 | AVG_2 | SUM_2 | Item 1 | A | 10 | 10 | 20 | 20 | Item 1 | B | 10 | 10 | 20 | 20 |
此外,如果部分為 3,則 A 和 B 程式碼的 AVG 和 SUM 將額外增加一行。這是動態的,使用者可以輸入此值。如何將多行展平?
在此要求中,項目 1 和程式碼 A 必須顯示第 1 部分總和和平均值,然後顯示第 2 部分總和和平均值,這可以根據部分列中的值進行更改。
感謝您對此的幫助!
以下查詢產生了我需要的結果。但是,如果有超過 2 個部分(數據庫列的一部分),則需要動態生成附加列 AVG3、SUM3。
select a.ITEM, a.CD, a.AVG1, b.SUM1, a.AVG2, b.SUM2 from ( SELECT substr(row_name,1,POSITION('|' IN row_name)-1) as item substr(row_name,POSITION('|' IN row_name)+1,99) as cd, AVG1, AVG2 FROM crosstab('SELECT item||''|''||cd, part::text, cnt::text FROM a WHERE type = ''AVG'' order by item, cd, part',1) AS ct (row_name text, AVG1 text, AVG2 text) ) a, ( SELECT substr(row_name,1,POSITION('|' IN row_name)-1) as name, substr(row_name,POSITION('|' IN row_name)+1,99) as cd, SUM1, SUM2 FROM crosstab('SELECT item||''|''||cd, part::text, cnt::text FROM a WHERE type = ''SUM'' order by item, cd, part',1) AS ct (row_name text, SUM1 text, SUM2 text) ) b where a.item = b.item and a.cd = b.cd;
我更喜歡使用過濾聚合而不是相當繁瑣(在我看來)的
crosstab()
功能:select item, cd, avg(cnt) filter (where type = 'AVG' and part = 1) as avg_1, sum(cnt) filter (where type = 'SUM' and part = 1) as sum_1, avg(cnt) filter (where type = 'AVG' and part = 2) as avg_2, sum(cnt) filter (where type = 'SUM' and part = 2) as sum_2 from the_table group by item, cd order by item, cd
我認為這也使添加新列更容易。