外部应用中的 WITH 语句
WITH-statement inside Outer Apply
我正在使用 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,1,'') as Ids,
Stuff((select ',' + Convert(varchar(10),t2.Number)
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 Numbers
)x
outer apply
里面的select-cases/queries是一样的。我想知道是否可以重用这个查询?我尝试在 outer apply
中创建一个 CTE,但这似乎不被 SQL 服务器接受:
select max(x.Ids), max(x.Number), (select country,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 ',' + Convert(varchar(10),t2.Id)
from Test_CTE t2
for xml path(''),type).value('(./text())[1]','varchar(10)'),1,1,'') as Ids,
Stuff((select ',' + Convert(varchar(10),t2.Number)
from Test_CTE t2
for xml path(''),type).value('(./text())[1]','varchar(10)'),1,1,'') as Numbers
)x
以上尝试出现以下错误:
Incorrect syntax near the keyword 'with'.
在您的 for xml
中,您可以包含两列,避免与“,”连接,并保留列的名称,以便输出的值包含在元素中。
然后,在外层逻辑中,可以查询具体的有问题的元素,转换为字符串,结束标签替换为空字符串,开始标签替换为逗号,第一个逗号用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, 'a', 'z');
你可以这样做:
select [Json] = (select t.country, t.city for json path),
Ids = stuff(replace(replace(convert(varchar(max),
ap._xml.query('./Id')
),'<Id>', ','),'</Id>',''), 1, 1, ''),
Nums = stuff(replace(replace(convert(varchar(max),
ap._xml.query('./Number')
),'<Number>', ','),'</Number>',''), 1, 1, '')
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;
并得到这样的输出:
Json
Ids
Nums
[{"country":"b","city":"y"}]
2
102
[{"country":"a","city":"z"}]
1,3
101,103
但我不知道你是否认为新方法比原来的方法更优雅。我会说它是,但仍然很丑陋。请记住,较新版本的 sql 服务器具有 string_agg
功能,可以为您完成这一切。
我正在使用 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,1,'') as Ids,
Stuff((select ',' + Convert(varchar(10),t2.Number)
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 Numbers
)x
outer apply
里面的select-cases/queries是一样的。我想知道是否可以重用这个查询?我尝试在 outer apply
中创建一个 CTE,但这似乎不被 SQL 服务器接受:
select max(x.Ids), max(x.Number), (select country,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 ',' + Convert(varchar(10),t2.Id)
from Test_CTE t2
for xml path(''),type).value('(./text())[1]','varchar(10)'),1,1,'') as Ids,
Stuff((select ',' + Convert(varchar(10),t2.Number)
from Test_CTE t2
for xml path(''),type).value('(./text())[1]','varchar(10)'),1,1,'') as Numbers
)x
以上尝试出现以下错误:
Incorrect syntax near the keyword 'with'.
在您的 for xml
中,您可以包含两列,避免与“,”连接,并保留列的名称,以便输出的值包含在元素中。
然后,在外层逻辑中,可以查询具体的有问题的元素,转换为字符串,结束标签替换为空字符串,开始标签替换为逗号,第一个逗号用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, 'a', 'z');
你可以这样做:
select [Json] = (select t.country, t.city for json path),
Ids = stuff(replace(replace(convert(varchar(max),
ap._xml.query('./Id')
),'<Id>', ','),'</Id>',''), 1, 1, ''),
Nums = stuff(replace(replace(convert(varchar(max),
ap._xml.query('./Number')
),'<Number>', ','),'</Number>',''), 1, 1, '')
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;
并得到这样的输出:
Json | Ids | Nums |
---|---|---|
[{"country":"b","city":"y"}] | 2 | 102 |
[{"country":"a","city":"z"}] | 1,3 | 101,103 |
但我不知道你是否认为新方法比原来的方法更优雅。我会说它是,但仍然很丑陋。请记住,较新版本的 sql 服务器具有 string_agg
功能,可以为您完成这一切。