如何使用 STRING_AGG() 以升序分隔字符串逗号

Posted

技术标签:

【中文标题】如何使用 STRING_AGG() 以升序分隔字符串逗号【英文标题】:How to get strings comma separated in ascending order with STRING_AGG() 【发布时间】:2021-06-26 01:44:24 【问题描述】:

我的桌子是这样的

Color  Order 
------------
Red    49
Blue   32
Green  80
Green  30
Blue   93
Blue   77
Red    20
Green  54
Red    59
Red    42
Red    81
Green  35
Blue   91

我的查询是

SELECT Color, Count(*) AS Count, STRING_AGG(Order,',') AS AggOrder
FROM MyTable
GROUP BY Color

当我按颜色分组并聚合时,我得到未排序的订单

类似的东西

Color  Count  AggOrder
------------------------------
Red    5      49,20,59,42,81
Blue   4      32,93,77,91
Green  4      80,30,54,35

问题: AggOrder 是无序的 49,20,59,42,81

我想订购

所以最终结果是

Color  Count  AggOrder
------------------------------
Red    5      20,42,49,59,81
Blue   4      32,77,91,93
Green  4      30,35,54,80

我试过这个查询

SELECT Color, Count(*) AS Count, STRING_AGG(Order,',') AS AggOrder
FROM MyTable
GROUP BY Color
ORDER BY Order

但这会报错。

知道如何解决这个问题吗?

【问题讨论】:

【参考方案1】:

在您对STRING_AGG 的调用中添加ORDER BY 子句:

SELECT
    Color,
    COUNT(*) AS Count,
    STRING_AGG([Order], ',') WITHIN GROUP (ORDER BY CAST([Order] AS INT)) AS AggOrder
FROM MyTable
GROUP BY Color;

Order 列上有两个 cmets。首先,ORDER 是保留的 SQL Server 关键字,您粘贴在问题中的查询甚至不会按给定的方式运行,因为 ORDER 在用作数据库对象名称时需要转义。您应该避免使用关键字命名列、表等。其次,假设Order 列是文本,如果你想用它作为数字排序,你应该先转换为整数。

【讨论】:

我认为(或希望)[Order] 列更有可能是int,因此应为STRING_AGG(CAST([Order] AS varchar(10))) WITHIN... @Charliefacepalm 是的……我也想过这个,你可能是对的。【参考方案2】:

你可以使用within group语法

SELECT Color
    , Count(*) AS Count
    , STRING_AGG([Order],',') WITHIN GROUP (ORDER BY [Order]) AS AggOrder
FROM MyTable
GROUP BY Color

【讨论】:

【参考方案3】:

对于 SQL Server 2017 或更高版本,您已经得到了答案。但如果 SQL Server 早于 2017 年,您可以使用 stuff() 和 XML PATH FOR() 来获得您想要的结果:

由于您使用的是 SQL Server 2017 或更高版本,请不要使用此解决方案,而是使用带有 string_agg() 的解决方案,因为该解决方案更快且易于实施。

架构:

 create table MyTable (color varchar(10), [order] int);
 insert into MyTable  values('Red',    49);
 insert into MyTable  values('Blue',   32);
 insert into MyTable  values('Green',  80);
 insert into MyTable  values('Green',  30);
 insert into MyTable  values('Blue',   93);
 insert into MyTable  values('Blue',   77);
 insert into MyTable  values('Red',    20);
 insert into MyTable  values('Green',  54);
 insert into MyTable  values('Red',    59);
 insert into MyTable  values('Red',    42);
 insert into MyTable  values('Red',    81);
 insert into MyTable  values('Green',  35);
 insert into MyTable  values('Blue',   91);

查询:

 SELECT color,count(*) [Count],
    STUFF((SELECT ',' + COALESCE(LTRIM(RTRIM([order])), '') 
    FROM MyTable mt 
        WHERE mt.color = m.color
        order by [order]
    FOR XML PATH('') ), 1, 1, ''
    ) as AggOrder
 FROM MyTable m
 group by color
 

输出:

color Count AggOrder
Blue 4 32,77,91,93
Green 4 30,35,54,80
Red 5 20,42,49,59,81

db小提琴here

【讨论】:

以上是关于如何使用 STRING_AGG() 以升序分隔字符串逗号的主要内容,如果未能解决你的问题,请参考以下文章

MS SQL Server的STRING_SPLIT和STRING_AGG函数

String_agg 模拟 [重复]

PostgreSql 聚合函数string_agg与array_agg

MySql分隔字符串并排序

16.数字大小升降排序编写

如何在 SQL 中对数组进行 string_agg?