PostgreSQL 9.3:使用 array_agg 函数以特定格式显示结果

PostgreSQL 9.3: Display result in specific format using array_agg function

我想把下面给定的记录显示成特定的格式table 如下所示 table.

正在创建 table:Test_1

CREATE TABLE Test_1
(
ColumnA varchar,
ColumnB varchar
);

插入记录:

INSERT INTO Test_1 values('A101','B101'),('A102','B102'),
            ('A103','B103'),('A104','B104'),
            ('A105','B105'),('A106','B106'),
            ('A107','B107'),('A108','B108'),
            ('A109','B109'),('A201','B201');

我想这样显示结果:

预期结果

ColumnA     ColumnX
---------------------------------------------------------------------------------------------------------------------------------------
A101        "B101" =  1, "B102" = 0, "B103" = 0, "B104" = 0, "B105" = 0, "B106" = 0, "B107" = 0, "B108" = 0, "B109" = 0, "B201" = 0
A102        "B101" =  0, "B102" = 1, "B103" = 0, "B104" = 0, "B105" = 0, "B106" = 0, "B107" = 0, "B108" = 0, "B109" = 0, "B201" = 0
A103        "B101" =  0, "B102" = 0, "B103" = 1, "B104" = 0, "B105" = 0, "B106" = 0, "B107" = 0, "B108" = 0, "B109" = 0, "B201" = 0
A104        "B101" =  0, "B102" = 0, "B103" = 0, "B104" = 1, "B105" = 0, "B106" = 0, "B107" = 0, "B108" = 0, "B109" = 0, "B201" = 0
A105        "B101" =  0, "B102" = 0, "B103" = 0, "B104" = 0, "B105" = 1, "B106" = 0, "B107" = 0, "B108" = 0, "B109" = 0, "B201" = 0
A106        "B101" =  0, "B102" = 0, "B103" = 0, "B104" = 0, "B105" = 0, "B106" = 1, "B107" = 0, "B108" = 0, "B109" = 0, "B201" = 0
A107        "B101" =  0, "B102" = 0, "B103" = 0, "B104" = 0, "B105" = 0, "B106" = 0, "B107" = 1, "B108" = 0, "B109" = 0, "B201" = 0
A108        "B101" =  0, "B102" = 0, "B103" = 0, "B104" = 0, "B105" = 0, "B106" = 0, "B107" = 0, "B108" = 1, "B109" = 0, "B201" = 0
A109        "B101" =  0, "B102" = 0, "B103" = 0, "B104" = 0, "B105" = 0, "B106" = 0, "B107" = 0, "B108" = 0, "B109" = 1, "B201" = 0
A201        "B101" =  0, "B102" = 0, "B103" = 0, "B104" = 0, "B105" = 0, "B106" = 0, "B107" = 0, "B108" = 0, "B109" = 0, "B201" = 1

我正在使用以下脚本来完成我的一半工作:

SELECT columnA, array_agg(ColumnB) AS ColumnX
FROM  (
   SELECT ColumnA, right(ColumnA, -1)::int AS sortb
    , CASE WHEN m.ColumnB IS NULL THEN 0 ELSE 1 END AS ColumnB
   FROM        (SELECT DISTINCT ColumnA FROM Test_1) b
   CROSS  JOIN (SELECT DISTINCT ColumnB FROM Test_1) a
   LEFT   JOIN Test_1 m USING (ColumnA, ColumnB)
   ORDER  BY sortb, right(ColumnB, -1)::int 
   ) sub
GROUP  BY 1, sortb
ORDER  BY sortb;

上面的脚本给出了以下结果:

获取结果:

ColumnA          ColumnX
---------------------------------------
A101        {1,0,0,0,0,0,0,0,0,0}
A102        {0,1,0,0,0,0,0,0,0,0}
A103        {0,0,1,0,0,0,0,0,0,0}
A104        {0,0,0,1,0,0,0,0,0,0}
A105        {0,0,0,0,1,0,0,0,0,0}
A106        {0,0,0,0,0,1,0,0,0,0}
A107        {0,0,0,0,0,0,1,0,0,0}
A108        {0,0,0,0,0,0,0,1,0,0}
A109        {0,0,0,0,0,0,0,0,1,0}
A201        {0,0,0,0,0,0,0,0,0,1}

问题:如何在ColumnX中的值前面加上columnB值?

只是简单的修改
还根据您的评论中的要求添加了实际计数。

SELECT columnA, array_agg(ColumnB) AS ColumnX
FROM  (
   SELECT ColumnA, right(ColumnA, -1)::int AS sorta
        , '"' || ColumnB || '" = ' || count(m.ColumnB) AS ColumnB
   FROM        (SELECT DISTINCT ColumnA FROM Test_1) b
   CROSS  JOIN (SELECT DISTINCT ColumnB FROM Test_1) a
   LEFT   JOIN Test_1 m USING (ColumnA, ColumnB)
   GROUP  BY ColumnA, ColumnB
   ORDER  BY sorta, right(ColumnB, -1)::int 
   ) sub
GROUP  BY 1, sorta
ORDER  BY sorta;

SQL Fiddle.

一个数组

根据评论:

SELECT ARRAY[columnA] || array_agg(ColumnB) AS ColumnX
FROM  (
   SELECT ColumnA, right(ColumnA, -1)::int AS sorta
        , '"' || ColumnB || '" = ' || count(m.ColumnB) AS ColumnB
   FROM        (SELECT DISTINCT ColumnA FROM Test_1) b
   CROSS  JOIN (SELECT DISTINCT ColumnB FROM Test_1) a
   LEFT   JOIN Test_1 m USING (ColumnA, ColumnB)
   GROUP  BY ColumnA, ColumnB
   ORDER  BY right(ColumnB, -1)::int, sorta
   ) sub
GROUP  BY columnA, sorta
ORDER  BY sorta;
SELECT columnA, array_agg(ColumnB) AS ColumnX
FROM  (
  SELECT ColumnA, right(ColumnA, -1)::int AS sortb
    , CASE WHEN m.ColumnB IS NULL THEN NULL ELSE m.ColumnB||'='||( count(m.ColumnB)) END AS ColumnB
   FROM        (SELECT DISTINCT ColumnA FROM Test_1) b
   CROSS  JOIN (SELECT DISTINCT ColumnB FROM Test_1) a
   LEFT   JOIN Test_1 m USING (ColumnA, ColumnB)
 group by ColumnA,m.ColumnB,ColumnB
   ORDER  BY sortb, right(ColumnB, -1)::int 

   ) sub
GROUP  BY 1, sortb
ORDER  BY sortb;