[英]PostgreSQL 9.3: Dynamic pivot table
我有一個被稱為包含兩列分別是矩陣表cola
和colb
,如下圖所示:
表 :矩陣
create table matrix
(
cola varchar(10),
colb varchar(10)
);
行插入 :
insert into matrix values('A1','B1'),('A2','B2'),('A3','B3'),('A4','B4'),
('A5','B5'),('A6','B6'),('A7','B7'),('A8','B8'),
('A9','B9'),('A10','B10'),('A11','B11'),('A12','B12'),
('A13','B13'),('A14','B14'),('A15','B15'),('A16','B16'),
('A17','B17'),('A18','B18'),('A19','B19'),('A20','B20'),
('A21','B21'),('A22','B22'),('A23','B23'),('A24','B24'),
('A25','B25'),('A26','B26'),('A27','B27'),('A28','B28'),
('A29','B29'),('A30','B30');
注意 :我想以矩陣形式顯示結果並計算哪些列屬於彼此,並為每個列分配矩陣中的值。 我僅添加了30條記錄作為示例,但也可能有數千條記錄。 因此,我需要為此准備一個動態數據透視表。 預期結果如下圖所示。
預期結果 :
A1 A2 A3 A4 A5 A6 ................ A30
------------------------------------------------------------------
B1 | 1 0 0 0 0 0 0
|
B2 | 0 1 0 0 0 0 0
|
B3 | 0 0 1 0 0 0 0
|
B4 | 0 0 0 1 0 0 0
|
B5 | 0 0 0 0 1 0 0
|
B6 | 0 0 0 0 0 1 0
. |
. |
. |
. |
B30| 0 0 0 0 0 0 1
您可以使用附加模塊tablefunc中的 crosstab()
來執行此操作 :
SELECT b
, COALESCE(a1, 0) AS "A1"
, COALESCE(a2, 0) AS "A2"
, COALESCE(a3, 0) AS "A3"
, ... -- all the way up to "A30"
FROM crosstab(
'SELECT colb, cola, 1 AS val FROM matrix
ORDER BY 1,2'
, $$SELECT 'A'::text || g FROM generate_series(1,30) g$$
) AS t (b text
, a1 int, a2 int, a3 int, a4 int, a5 int, a6 int
, a7 int, a8 int, a9 int, a10 int, a11 int, a12 int
, a13 int, a14 int, a15 int, a16 int, a17 int, a18 int
, a19 int, a20 int, a21 int, a22 int, a23 int, a24 int
, a25 int, a26 int, a27 int, a28 int, a29 int, a30 int);
如果NULL
而不是0
也可以,則在外部查詢中可以只是SELECT *
。
詳細說明:
這里的特殊“難點”:沒有實際的“值”。 因此,將1 AS val
添加為最后一列。
在單個查詢中不可能進行完全動態的查詢(結果類型未知)。 您需要兩個查詢。 首先動態地構建類似於上述的語句,然后執行它。 細節:
如果超過最大列數(1600) ,則經典的交叉表是不可能的,因為結果無法用單獨的列表示。 (此外,人眼幾乎無法讀取具有這么多列的表格)
數組或文檔類型(例如hstore
或jsonb
是替代方法。 這是數組的解決方案:
SELECT colb, array_agg(cola) AS colas
FROM (
SELECT colb, right(colb, -1)::int AS sortb
, CASE WHEN m.cola IS NULL THEN 0 ELSE 1 END AS cola
FROM (SELECT DISTINCT colb FROM matrix) b
CROSS JOIN (SELECT DISTINCT cola FROM matrix) a
LEFT JOIN matrix m USING (colb, cola)
ORDER BY sortb, right(cola, -1)::int
) sub
GROUP BY 1, sortb
ORDER BY sortb;
使用以下方法構建完整的值網格:
(SELECT DISTINCT colb FROM matrix) b CROSS JOIN (SELECT DISTINCT cola FROM matrix) a
LEFT JOIN
現有組合,按名稱的數字部分排序並聚合成數組。
right(colb, -1)::int
修剪'A3'中的前導字符並將數字強制轉換為整數,以便我們獲得適當的排序順序。 如果您只想要一個0
x = y
1
的表,其中x = y
,則可以便宜一些:
SELECT x, array_agg((x = y)::int) AS y_arr
FROM generate_series(1,10) x
, generate_series(1,10) y
GROUP BY 1
ORDER BY 1;
SQL Fiddle建立在您在注釋中提供的那個位置。
請注意,sqlfiddle.com當前存在一個錯誤,該錯誤會殺死數組值的顯示。 因此,我在此處發送text
以解決該問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.