按汇总汇总(ARRAY_AGG)?

时间:2013-03-27 14:54:45

标签: sql postgresql postgresql-9.1

假设我有一个包含3列的简单表agg_test - idcolumn_1column_2。数据集,例如:

id|column_1|column_2
--------------------
 1|       1|       1
 2|       1|       2
 3|       1|       3
 4|       1|       4
 5|       2|       1
 6|       3|       2
 7|       4|       3
 8|       4|       4
 9|       5|       3
10|       5|       4 

像这样的查询(使用自我加入):

SELECT
  a1.column_1,
  a2.column_1,
  ARRAY_AGG(DISTINCT a1.column_2 ORDER BY a1.column_2)
FROM agg_test a1
JOIN agg_test a2 ON a1.column_2 = a2.column_2 AND a1.column_1 <> a2.column_1
WHERE a1.column_1 = 1
GROUP BY a1.column_1, a2.column_1

会产生这样的结果:

column_1|column_1|array_agg
---------------------------
       1|       2|      {1}
       1|       3|      {2}
       1|       4|    {3,4}
       1|       5|    {3,4}

我们可以看到,对于连接表中的值4和5,我们在最后一列中得到相同的结果。那么,是否有可能以某种方式对结果进行分组,例如:

column_1|column_1|array_agg
---------------------------
       1|     {2}|      {1}
       1|     {3}|      {2}
       1|   {4,5}|    {3,4}

感谢您的回答。如果有任何不清楚或可以更好的方式呈现 - 请在评论中告诉我,我会尽量使这个问题尽可能可读。

2 个答案:

答案 0 :(得分:4)

我不确定你是否可以通过数组聚合。如果你能在这里采用一种方法:

select col1, array_agg(col2), ar
from (SELECT a1.column_1 as col1, a2.column_1 as col2,
             ARRAY_AGG(DISTINCT a1.column_2 ORDER BY a1.column_2) as ar
      FROM agg_test a1 JOIN
           agg_test a2
           ON a1.column_2 = a2.column_2 AND a1.column_1 <> a2.column_1
      WHERE a1.column_1 = 1
      GROUP BY a1.column_1, a2.column_1
     ) t
group by col1, ar

另一种方法是使用array_dims将数组值转换为字符串。

答案 1 :(得分:2)

你也可以尝试这样的事情:

SELECT DISTINCT
  a1.column_1,
  ARRAY_AGG(a2.column_1) OVER (
    PARTITION BY
      a1.column_1,
      ARRAY_AGG(DISTINCT a1.column_2 ORDER BY a1.column_2)
  ) AS "a2.column_1 agg",
  ARRAY_AGG(DISTINCT a1.column_2 ORDER BY a1.column_2)
FROM agg_test a1
JOIN agg_test a2 ON a1.column_2 = a2.column_2 AND a1.column_1  a2.column_1
WHERE a1.column_1 = 1
GROUP BY a1.column_1, a2.column_1
;

(突出显示的部分与您在问题中发布的查询不同。)

上面使用窗口ARRAY_AGGa2.column_1的值与另一个ARRAY_AGG组合在一起,使用后者的结果作为分区条件之一。如果没有DISTINCT,则会为您的示例生成两个{4,5}行。因此,需要DISTINCT来消除重复项。

这是一个SQL小提琴演示:http://sqlfiddle.com/#!1/df5c3/4

请注意,窗口ARRAY_AGG不能像ORDER BY那样“正常”对应。这意味着列表中a2.column_1值的顺序将是不确定的,尽管在链接演示中它恰好与预期输出中的值相匹配。