簡體   English   中英

PostgreSQL 9.3:動態數據透視表

[英]PostgreSQL 9.3: Dynamic pivot table

我有一個被稱為包含兩列分別是矩陣表colacolb ,如下圖所示:

:矩陣

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) ,則經典的交叉表是不可能的,因為結果無法用單獨的列表示。 (此外,人眼幾乎無法讀取具有這么多列的表格)

數組或文檔類型(例如hstorejsonb是替代方法。 這是數組的解決方案:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM