替代 SQL Server 2016 之前的 STRING_AGG

问题描述 投票:0回答:2

我需要按一组值以及每组的所有匹配行号/id:s 对表进行分组。此操作必须在 SQL Server 2016 的范围内完成。

假设我有下表(地点):

身份证 国家 城市
1 瑞典 斯德哥尔摩
2 挪威 奥斯陆
3 冰岛 雷克雅未克
4 瑞典 斯德哥尔摩

我想要的结果(没有大括号,因为 Stack Overflow 认为这是代码,阻止我发布):

身份证 杰森
1,4 “国家”:“瑞典”,“城市”:“斯德哥尔摩”
2 “国家”:“挪威”,“城市”:“奥斯陆”
3 “国家”:“冰岛”,“城市”:“雷克雅未克”

在 SQL Server 2017 中,可以通过以下方式实现上述结果:

SELECT STRING_AGG(ID) ID, (SELECT Country, City FOR JSON PATH) Json
FROM Places GROUP BY Country, City

我使用下面的代码在 SQL Server 2016 中获得了类似的结果。 (但是以我实际的数据量和列数来说,这个解决方案太慢了。)

SELECT DISTINCT Country, City INTO #temp FROM Places
SELECT (SELECT ID From Places WHERE Country = P.Country AND City = P.City FOR JSON PATH) ID, 
(SELECT Country, City FOR JSON Path) Json FROM #temp P

有没有更有效的方法来实现我所追求的结果?

编辑:正如人们建议我尝试“FOR XML Path”我尝试了下面的代码。这会出现以下错误“Places.ID 在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中”:

SELECT stuff((select ',' + cast(ID as varchar(max)) for xml path ('')), 1, 1, '') ID, 
(SELECT Country, City FOR JSON PATH) Json
FROM Places GROUP BY Country, City
sql-server t-sql group-by string-aggregation
2个回答
2
投票

这是您可以尝试的解决方案

for xml path

基本上选择并分组所需的

json
列,并使用
apply
,使用
for xml path
解决方案聚合相关的 ID 值;因为外部查询需要引用
apply
的输出,它也需要聚合,所以我选择使用
max

select max(x.Ids), (select country,city for json path) as [Json]
from t
outer apply (
    select Stuff((select ',' + Convert(varchar(10),t2.Id)
    from t t2
    where t2.city=t.city and t2.country=t.country
    for xml path(''),type).value('(./text())[1]','varchar(10)'),1,1,'') as Ids
)x
group by country,city

工作小提琴


0
投票

这是另一种可能的解决方案:

Declare @testTable Table (ID int, Country varchar(30), City varchar(30));
 Insert Into @testTable (ID, Country, City)
 Values (1, 'Sweden', 'Stockholm')
      , (2, 'Normway', 'Oslo')
      , (3, 'Iceland', 'Reykjavik')
      , (4, 'Sweden', 'Stockholm');

 Select Distinct
        ID = stuff((Select concat(',', tt2.ID)
                      From @testTable tt2
                     Where tt2.City = tt.City
                       And tt2.Country = tt.Country
                       For xml path (''), Type).value('.', 'varchar(10)'), 1, 1, '')
      , json = (Select Country, City For JSON PATH) 
   From @testTable      tt;

不知道这是否会表现得更好。本质上是一样的 - 只是使用 DISTINCT 而不是 GROUP BY。

© www.soinside.com 2019 - 2024. All rights reserved.