问题描述
我使用 for xml path
来聚合值:
select max(x.Ids),max(x.Number),(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,'') as Ids,Stuff((select ',t2.Number)
from t t2
where t2.city=t.city and t2.country=t.country
for xml path(''),'') as Numbers
)x
outer apply
中的选择案例/查询是相同的。我想知道是否可以重用这个查询?我尝试在 outer apply
内创建 CTE,但这似乎不被 sql Server 接受:
select max(x.Ids),city for json path) as [Json]
from t
outer apply (
with Test_CTE( Id,Number) AS (
SELECT ID,Number FROM t t2
where t2.city=t.city and t2.country=t.country
)
select Stuff((select ',t2.Id)
from Test_CTE t2
for xml path(''),t2.Number)
from Test_CTE t2
for xml path(''),'') as Numbers
)x
上述尝试给出了以下错误:
关键字“with”附近的语法不正确。
解决方法
在您的 for xml
中,您可以包含两列,避免使用“,”连接,并保留列的名称,以便输出的值包含在元素中。
然后,在外层逻辑中,您可以查询有问题的特定元素,转换为字符串,用空字符串替换结束标记,用逗号替换开始标记,并用{{1}杀死第一个逗号}.
在开始保存一些处理之前,您也可以考虑对源应用 stuff
子句。
所以,对于这样的数据:
distinct
你可以这样做:
declare @t table (Id int,Number int,country char(1),city char(1));
insert @t values
(1,101,'a','z'),(2,102,'b','y'),(3,103,'z');
得到这样的输出:
杰森 | ID | 数字 |
---|---|---|
[{"country":"b","city":"y"}] | 2 | 102 |
[{"country":"a","city":"z"}] | 1,3 | 101,103 |
但我不知道您是否认为新方法比原始方法更优雅。我会说它是,但仍然很丑陋。请记住,较新版本的 sql server 具有 select [Json] = (select t.country,t.city for json path),Ids = stuff(replace(replace(convert(varchar(max),ap._xml.query('./Id')
),'<Id>',','),'</Id>',''),1,Nums = stuff(replace(replace(convert(varchar(max),ap._xml.query('./Number')
),'<Number>','</Number>','')
from (select distinct t.city,t.country from @t t) t
cross apply (select _xml = (
select t2.Id,t2.Number
from @t t2
where t2.city = t.city and t2.country = t.country
for xml path(''),type
)) ap;
函数,可为您完成所有这些工作。