【问题标题】:Aggregate by aggregate (ARRAY_AGG)?按聚合 (ARRAY_AGG) 聚合?
【发布时间】:2013-03-27 14:54:44
【问题描述】:

假设我有一个简单的表 agg_test,它有 3 列 - 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}

感谢您的任何回答。如果有任何不清楚的地方或可以以更好的方式呈现,请在 cmets 中告诉我,我会尽量让这个问题更具可读性。

【问题讨论】:

    标签: sql postgresql postgresql-9.1


    【解决方案1】:

    我不确定您是否可以按数组聚合。如果可以,这是一种方法:

    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 将数组值转换为字符串。

    【讨论】:

      【解决方案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 Fiddle 演示:http://sqlfiddle.com/#!1/df5c3/4

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-30
        • 1970-01-01
        • 1970-01-01
        • 2015-10-21
        • 2017-09-24
        • 2014-10-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多