【问题标题】:Group by multiple columns and get result as an array in separate columns按多列分组并将结果作为单独列中的数组获取
【发布时间】:2019-10-09 22:33:45
【问题描述】:

我有一张如下表:

| col_A | col_B |
|-------|-------|
| 1     | 1     |
| 1     | 2     |
| 1     | 3     |
| 2     | 1     |
| 2     | 2     |
| 2     | 3     |
| 3     | 1     |
| 3     | 2     |

我想将结果分组并连接到一个数组中,如下所示:

| col_A | col_B |
|-------|-------|
| 1,2   | 1,2,3 |
| 3     |  1,2  |

我尝试编写查询:

SELECT col_A, array_agg(col_B ORDER BY col_B DESC) FROM table GROUP BY col_A;

但是,这会输出:

| col_A | col_B   |
|-------|---------|
| 1     | {1,2,3} |
| 2     | {1,2,3} |
| 3     | {1,2}   |

【问题讨论】:

    标签: sql arrays postgresql aggregate


    【解决方案1】:

    似乎您想聚合按col_a 分组的col_b,然后聚合按聚合数组分组的col_a。您可以使用嵌套查询来执行此操作,您已经完成了第一步:

    SELECT array_agg(col_a), col_b
    FROM (SELECT col_a, array_agg(DISTINCT col_b ORDER BY col_b) AS col_b
          FROM example GROUP BY col_a) grouped_b
    GROUP BY col_b;
    

    (online demo)

    【讨论】:

    • 您可能希望从聚合中删除 DISTINCT,但不确定您是否需要/想要这样做。
    【解决方案2】:

    在 Postgres 中,在子查询中对行进行排序通常比在聚合函数中添加 ORDER BY 子句便宜:

    SELECT array_agg(col_a) AS col_a, col_b
    FROM  (
       SELECT col_a, array_agg(col_b) AS col_b
       FROM  (TABLE tbl ORDER BY col_a, col_b) t
       GROUP  BY 1
       ORDER  BY 1
       ) sub
    GROUP  BY 2
    ORDER  BY 1;
    

    准确地产生您想要的结果,包括元素和行的顺序。

    db小提琴here

    第一个ORDER BY是在构造col_b中的数组之前对元素进行排序。
    第二个ORDER BY是在构造col_a中的数组之前对元素进行排序。
    第 3 个ORDER BY 是按照 OP 示例结果建议的顺序输出行。

    查询应该在没有第二个和第三个ORDER BY 的情况下工作相同,因为第一个订单被结转。但没有任何保证。 (查询大表时,并行性之类的事情可能会扰乱顺序。)呈现的查询保证产生所需的顺序。

    相关:

    关于GROUP BYORDER BY 中的位置引用:

    关于(TABLE tbl ORDER BY col_a, col_b)

    【讨论】:

    • GROUP BY 1ORDER BY 2 语法是什么,是指列索引吗?为什么要对它们进行排序(除了确保数组元素在外部分组比较中具有相同的顺序)?
    • @Bergi:我添加了一个链接来解释位置引用。以及每个ORDER BY的解释。
    • 谢谢,我从来没有见过序数来指代列。不过有道理!
    • @Bergi:我在这里使用它们是为了避免更多的打字。它是否更容易阅读和维护是一个有争议的问题。对于避免重复冗长的表达式或使用动态 SQL 最有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-31
    • 1970-01-01
    • 2011-02-08
    • 2013-08-02
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    相关资源
    最近更新 更多