我尝试创建一个可以像 this example 一样使用的通用函数在 SQL Server 2017 上使用新的 string_agg 内置函数
内部实现可能类似于以下内容
with tbl as(
select a.Id, c.Desc
from TableA a
join TableB b on b.aId = a.Id
join TableC c on c.Code = b.bCode
)
select distinct ID
, STUFF(( select ', ' + Desc from tbl t where t.ID = tbl.ID
for xml path(''),TYPE).value('.','VARCHAR(MAX)'),1,2,'') Desc
from tbl
但是如何接收字段键、要连接的字段、分隔符字符和作用域选择上下文呢?
是否与
Inline
or Multi-Statement Table-Valued Functions
有关?
最佳答案
好吧,这是一个丑陋的黑客,我现在必须去洗手,但它有效(在某种程度上:-D)
CREATE FUNCTION dbo.MyStringAgg(@SelectForXmlAuto XML,@Delimiter NVARCHAR(10))
RETURNS NVARCHAR(MAX)
AS
BEGIN
RETURN STUFF((
SELECT @Delimiter + A.nd.value(N'(@*)[1]',N'nvarchar(max)')
FROM @SelectForXmlAuto.nodes(N'/*') AS A(nd)
FOR XML PATH(''),TYPE
).value(N'.',N'nvarchar(max)'),1,LEN(@Delimiter),'');
END
GO
DECLARE @tbl TABLE(GroupId INT,SomeValue NVARCHAR(10));
INSERT INTO @tbl VALUES(1,'A1'),(1,'A2'),(2,'B1'),(3,'C1'),(3,'C2'),(3,'C3');
SELECT GroupId
,dbo.MyStringAgg((SELECT SomeValue
FROM @tbl AS t2
WHERE t2.GroupId=t.GroupId
FOR XML AUTO), N', ')
FROM @tbl AS t
GROUP BY GroupId;
GO
DROP FUNCTION dbo.MyStringAgg;
结果1 A1, A2
2 B1
3 C1, C2, C3
参数是FOR XML
括号内的子选择。这会将子选择结果作为 XML 隐式传递到函数中。老实说:我自己不会使用这个......
像这样的查询
SELECT GroupId
,STUFF((SELECT N', ' + SomeValue
FROM @tbl AS t2
WHERE t2.GroupId=t.GroupId
FOR XML PATH,TYPE).value(N'.','nvarchar(max)'),1,2,'')
FROM @tbl AS t
GROUP BY GroupId;
产生相同的结果并且几乎相同的输入量 - 但应该比调用慢的 UDF 更快......
关于sql-server - 在早期版本上创建用户定义的函数,如 SQL server 2017 STRING_AGG,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48783205/