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

时间:2015-03-25 04:39:14

标签: sql postgresql left-join aggregate-functions postgresql-9.3

我想将下表中的给定记录显示为特定格式 如下表所示。

创建表格: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}

问题:如何在columnB的价值前面添加ColumnX值?

2 个答案:

答案 0 :(得分:2)

这只是一个简单的修改 还添加了评论中要求的实际计数。

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;

答案 1 :(得分:1)

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;