我正在寻找一种将不同行中的字符串聚合为一行的方法.我希望在很多不同的地方都能做到这一点,所以有一个功能来促进这一点会很好.我try 过使用COALESCEFOR XML的解决方案,但它们不适合我.

字符串聚合将执行以下操作:

id | Name                    Result: id | Names
-- - ----                            -- - -----
1  | Matt                            1  | Matt, Rocks
1  | Rocks                           2  | Stylus
2  | Stylus

我已经考虑过用CLR-defined aggregate functions来代替COALESCEFOR XML,但显然SQL Azure does not支持CLR定义的东西,这对我来说是一件痛苦的事情,因为我知道能够使用它会为我解决很多问题.

是否有任何可能的解决方法,或类似的优化方法(可能没有CLR那么优化,但我会尽我所能)可以用来聚合我的东西?

推荐答案

SOLUTION

optimal的定义可能有所不同,但下面介绍如何使用常规Transact-SQL连接不同行的字符串,这在Azure中应该可以正常工作.

;WITH Partitioned AS
(
    SELECT 
        ID,
        Name,
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Name) AS NameNumber,
        COUNT(*) OVER (PARTITION BY ID) AS NameCount
    FROM dbo.SourceTable
),
Concatenated AS
(
    SELECT 
        ID, 
        CAST(Name AS nvarchar) AS FullName, 
        Name, 
        NameNumber, 
        NameCount 
    FROM Partitioned 
    WHERE NameNumber = 1

    UNION ALL

    SELECT 
        P.ID, 
        CAST(C.FullName + ', ' + P.Name AS nvarchar), 
        P.Name, 
        P.NameNumber, 
        P.NameCount
    FROM Partitioned AS P
        INNER JOIN Concatenated AS C 
                ON P.ID = C.ID 
                AND P.NameNumber = C.NameNumber + 1
)
SELECT 
    ID,
    FullName
FROM Concatenated
WHERE NameNumber = NameCount

EXPLANATION

该方法可归结为三个步骤:

  1. 使用OVERPARTITION分组对行进行编号,并根据连接需要对行进行排序.结果是Partitioned CTE.我们在每个分区中保留行数,以便以后过滤结果.

  2. 使用递归CTE(Concatenated)遍历行号(NameNumber列),将Name个值添加到FullName列.

  3. 过滤掉所有结果,但不包括NameNumber个最高的结果.

请记住,为了使此查询可预测,必须同时定义分组(例如,在您的场景中,将具有相同ID的行连接起来)和排序(我假设您只需在连接之前按字母顺序对字符串进行排序).

我用以下数据在SQL Server 2012上快速测试了该解决方案:

INSERT dbo.SourceTable (ID, Name)
VALUES 
(1, 'Matt'),
(1, 'Rocks'),
(2, 'Stylus'),
(3, 'Foo'),
(3, 'Bar'),
(3, 'Baz')

查询结果如下:

ID          FullName
----------- ------------------------------
2           Stylus
3           Bar, Baz, Foo
1           Matt, Rocks

Sql相关问答推荐

使用收件箱运行多个SQL Update字符串,但出现错误

IS True操作员

SQL从同一表连接列

为主表中的每一行查找N个最新行

如何在case语句中使用条件来计算成对变量

不可能在SQL MERGE子句中引发异常

MariaDB查询在逗号分隔的字符串中查找多个值

检索上一个星期四和上一个星期三

值对于类型字符来说太长

如何在AWS Athena中 Select JSON数组的最后一个元素?

从每月生成的系列中生成每日汇率

错误:postgresql 中缺少表评级的 FROM 子句条目

如何根据共同列值从两个表中包含列,但只包含左表中的行

MariaDB非常简单的MATCHAGAINST查询不使用FULLTEXT索引吗?

COBOL\DB2作业(job)需要帮助?快来获取专业指导!

如何在 SQL Server 中将 -13422.8450 舍入到 -13422.84

过滤具有一对多关系的两个表之间的数据

有没有一种方法可以将始终遵循序列的单个字段的值组合起来,以创建每个 ID 的所有移动?

CURRENT_ROW 窗口框架上的 SQL 滞后

连接表时避免重复