【问题标题】:Sqlite group_concat orderingSqlite group_concat 排序
【发布时间】:2010-12-26 05:21:43
【问题描述】:

在 Sqlite 中我可以使用 group_concat 来做:

1...A
1...B
1...C
2...A
2...B
2...C

1...C,B,A
2...C,B,A

但连接的顺序是随机的 - 根据文档。

我需要将 group_concat 的输出排序为

1...A,B,C
2...A,B,C

我该怎么做?

【问题讨论】:

    标签: sqlite group-concat


    【解决方案1】:

    你不能使用带有 order by 子句的子选择,然后对值进行分组吗?

    类似

    SELECT ID, GROUP_CONCAT(Val)
    FROM (
       SELECT ID, Val
       FROM YourTable
       ORDER BY ID, Val
       )
    GROUP BY ID;
    

    【讨论】:

    【解决方案2】:

    更准确地说,根据docs

    连接元素的顺序是任意的。

    这并不真正意味着随机,它只是意味着开发人员保留使用他们想要的任何顺序的权利,甚至对于不同的查询或在不同的 SQLite 版本中使用不同的顺序。

    在当前版本中,这种排序可能是 Adrian Stander 的答案所暗示的,因为他的代码似乎确实有效。因此,您可能只是通过一些单元测试来保护自己并收工。但是如果不仔细检查 SQLite 的源代码,您永远无法 100% 确定这将始终有效。

    如果您愿意从源代码构建 SQLite,也可以尝试编写自己的 user-defined aggregate function,但有更简单的方法。

    幸运的是,从版本 3.25.0 开始,您拥有 window functions,提供了一个可以保证工作的解决方案,尽管解决您的问题有点难看。

    正如您在文档中看到的,窗口函数有自己的ORDER BY 子句:

    在上面的示例中,窗口框架由上一行(“1 PRECEDING”)和下一行(“1 FOLLOWING”)之间的所有行组成,包括在内,其中行根据 ORDER BY 子句中的排序window-defn(在本例中为“ORDER BY a”)。

    请注意,仅此一项并不一定意味着所有聚合函数都尊重窗口框架内部的顺序,但如果您查看unit tests,您会发现这实际上是案例:

    do_execsql_test 4.10.1 {
      SELECT a, 
        count() OVER (ORDER BY a DESC),
        group_concat(a, '.') OVER (ORDER BY a DESC) 
      FROM t2 ORDER BY a DESC
    } {
      6 1 6
      5 2 6.5
      4 3 6.5.4
      3 4 6.5.4.3
      2 5 6.5.4.3.2
      1 6 6.5.4.3.2.1
      0 7 6.5.4.3.2.1.0
    }
    

    所以,总结起来,你可以写

    SELECT ID, GROUP_CONCAT(Val) OVER (PARTITION BY ID ORDER BY Val) FROM YourTable;
    

    导致:

    1|A
    1|A,B
    1|A,B,C
    2|A
    2|A,B
    2|A,B,C
    

    不幸的是,它还包含您所需聚合的每个前缀。相反,您希望指定窗口框架始终包含完整范围,然后丢弃冗余值,如下所示:

    SELECT DISTINCT ID, GROUP_CONCAT(Val)
    OVER (PARTITION BY ID ORDER BY Val ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
    FROM YourTable;
    

    或者像这样:

    SELECT * FROM (
        SELECT ID, GROUP_CONCAT(Val)
        OVER (PARTITION BY ID ORDER BY Val ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
        FROM YourTable
    )
    GROUP BY ID;
    

    【讨论】:

    • 太棒了。感谢分享,我自己永远也想不通……
    • 同意!这是什么魔法!!? :-)(也为我工作)
    【解决方案3】:

    偶然发现了潜在的排序问题,我尝试了这个: (...在 10.4.18-MariaDB 上)

    select GROUP_CONCAT(ex.ID) as ID_list
    FROM (
    SELECT usr.ID
    FROM (
    SELECT u1.ID as ID
    FROM table_users u1
    ) usr
    GROUP BY ID
    ) ex
    

    ... 并找到已排序的序列化 ID_list! 但我没有解释这个现在“正确”(?)的结果。

    【讨论】:

    • 问题是关于 SQLite 而不是 MariaDB。
    猜你喜欢
    • 2016-02-14
    • 2019-03-25
    • 1970-01-01
    • 2016-05-31
    • 2013-09-17
    • 2013-07-24
    • 2013-04-12
    • 2017-11-26
    • 2015-06-28
    相关资源
    最近更新 更多