use*_*781 40 sqlite group-concat
在Sqlite中我可以使用group_concat来做:
1...A
1...B
1...C
2...A
2...B
2...C
1...C,B,A
2...C,B,A
Run Code Online (Sandbox Code Playgroud)
但根据文档,连接的顺序是随机的.
我需要将group_concat的输出排序为
1...A,B,C
2...A,B,C
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
Adr*_*der 66
你能否在order by子句中使用subselect,然后对这些值进行分组?
就像是
SELECT ID, GROUP_CONCAT(Val)
FROM (
SELECT ID, Val
FROM YourTable
ORDER BY ID, Val
)
GROUP BY ID;
Run Code Online (Sandbox Code Playgroud)
更准确地说,根据文档:
连接元素的顺序是任意的。
这并不意味着随机,它只是意味着开发人员保留使用他们想要的任何顺序的权利,甚至是针对不同查询或不同 SQLite 版本的不同顺序。
对于当前版本,这种排序可能是 Adrian Stander 的答案所暗示的,因为他的代码似乎确实有效。因此,您可能只是通过一些单元测试来保护自己,然后就收工了。但是,如果不仔细检查 SQLite 的源代码,您永远无法 100% 确定这将始终有效。
如果您愿意从源代码构建 SQLite,您也可以尝试编写自己的用户定义聚合函数,但有一个更简单的方法。
幸运的是,从 3.25.0 版本开始,您有了window functions,提供了一个有保证的工作,尽管对您的问题有些难看。
正如您在文档中看到的那样,窗口函数有自己的ORDER BY子句:
在上面的例子中,窗口框架由前一行(“1 PRECEDING”)和下一行(“1 FOLLOWING”)之间的所有行组成,其中行根据 window-defn 中的 ORDER BY 子句进行排序(在本例中为“ORDER BY a”)。
请注意,仅凭这一点并不一定意味着所有聚合函数都遵守窗口框架内的排序,但是如果您查看单元测试,您会发现实际上是这样:
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
}
Run Code Online (Sandbox Code Playgroud)
所以,总结一下,你可以写
SELECT ID, GROUP_CONCAT(Val) OVER (PARTITION BY ID ORDER BY Val) FROM YourTable;
Run Code Online (Sandbox Code Playgroud)
导致:
1|A
1|A,B
1|A,B,C
2|A
2|A,B
2|A,B,C
Run Code Online (Sandbox Code Playgroud)
不幸的是,它还包含您所需聚合的每个前缀。相反,您希望指定窗口框架始终包含完整范围,然后丢弃冗余值,如下所示:
SELECT DISTINCT ID, GROUP_CONCAT(Val)
OVER (PARTITION BY ID ORDER BY Val ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM YourTable;
Run Code Online (Sandbox Code Playgroud)
或者像这样:
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;
Run Code Online (Sandbox Code Playgroud)