sql-server - 在早期版本上创建用户定义的函数,如 SQL server 2017 STRING_AGG

标签 sql-server user-defined-functions string-aggregation

我尝试创建一个可以像 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/

相关文章:

php - 电话可以用来传播本地主机的使用吗?

ado.net - 如何在 ADO.NET 中为表值函数调用传递默认关键字

mysql - 获取一行中 2 行值的结果

sql - 为什么 PostgreSQL 比其他数据库更难管理/维护

sql-server - SQL Server rtrim ltrim 和 charindex

sql-server - SSRS : String concatenation with nullable strings

tsql - T-SQL - 交叉应用到 PIVOT? (将数据透视表与表值函数一起使用)?

scala - 将多个(任意数量)spark DataFrame 列连接成一个 "|"分隔字符串

sql - Oracle:将子查询中的多个结果合并为一个逗号分隔的值

sql - Oracle 用逗号连接列