Sql (列)在(分区…)上方?对包含行进行分组,而不对结果本身进行分组

Sql (列)在(分区…)上方?对包含行进行分组,而不对结果本身进行分组,sql,sql-server,sql-server-2008,tsql,string-aggregation,Sql,Sql Server,Sql Server 2008,Tsql,String Aggregation,我需要一种方法,在一种窗口函数中对每个组的所有行进行串联,比如如何通过。。。每个组中所有行的合计计数将在每个特定组中重复。我需要一些类似的东西,但每个组的所有值在每个组中重复的字符串串联 以下是一些示例数据和我的期望结果,以更好地说明我的问题: grp | val ------------ 1 | a 1 | b 1 | c 1 | d 2 | x 2 | y 2 | z 以下是我想要的结果: grp | val | gro

我需要一种方法,在一种窗口函数中对每个组的所有行进行串联,比如如何通过。。。每个组中所有行的合计计数将在每个特定组中重复。我需要一些类似的东西,但每个组的所有值在每个组中重复的字符串串联

以下是一些示例数据和我的期望结果,以更好地说明我的问题:

grp  |  val
------------
1    |  a
1    |  b
1    |  c
1    |  d
2    |  x
2    |  y
2    |  z
以下是我想要的结果:

grp  |   val  |  groupcnct
---------------------------------
1    |   a    |  abcd
1    |   b    |  abcd
1    |   c    |  abcd
1    |   d    |  abcd
2    |   x    |  xyz
2    |   y    |  xyz
2    |   z    |  xyz
下面是这个问题中真正棘手的部分: 我的特殊情况使我无法两次引用同一个表,因为我实际上是在递归CTE中这样做的,所以我不能进行CTE的自连接,否则它会抛出错误

我完全明白,一个人可以做以下事情:

SELECT      a.*, b.groupcnct
FROM        tbl a
CROSS APPLY (
            SELECT STUFF((
                        SELECT '' + aa.val 
                        FROM   tbl aa
                        WHERE  aa.grp = a.grp
                        FOR XML PATH('')
                   ), 1, 0, '') AS groupcnct
            ) b
但正如您所看到的,这在查询中引用了两次tbl

我只能引用tbl一次,因此我想知道是否可以对组连接进行窗口化我对TSQL有点陌生,因为我来自MySQL的背景,所以不确定是否可以这样做

创建表:
我尝试使用纯CTE方法:认为它更快


但是基准测试告诉我们,使用子查询或交叉应用来自XML路径的结果更好,因为它们更快:

您是否可以将您的内容放在select中,或者您遇到了相同的问题?我将“tbl”替换为“TEMP.TEMP123”

Select 
A.*
, [GROUPCNT] = STUFF((
                        SELECT '' + aa.val 
                        FROM  TEMP.TEMP123 AA
                        WHERE  aa.grp = a.grp
                        FOR XML PATH('')
                   ), 1, 0, '') 


 from TEMP.TEMP123 A

这对我有用-想看看这对你是否也有用

在sql 2017中,您可以使用STRING_AGG函数:

SELECT STRING_AGG(T.val, ',') AS val
    , T.grp
FROM @tbl AS T
GROUP BY T.grp

我知道这篇文章很老,但以防万一,有人还在想,你们可以创建一个连接行值的标量函数

IF OBJECT_ID('dbo.fnConcatRowsPerGroup','FN') IS NOT NULL
DROP FUNCTION dbo.fnConcatRowsPerGroup
GO
CREATE FUNCTION dbo.fnConcatRowsPerGroup 
    (@grp as int) RETURNS VARCHAR(MAX)
AS 
BEGIN
    DECLARE @val AS VARCHAR(MAX)

    SELECT @val = COALESCE(@val,'')+val
    FROM tbl
    WHERE grp = @grp

    RETURN @val;
END
GO


select *, dbo.fnConcatRowsPerGroup(grp)
from tbl
以下是我查询示例表得到的结果集:

grp  |   val  |  (No column name)
---------------------------------
1    |   a    |  abcd
1    |   b    |  abcd
1    |   c    |  abcd
1    |   d    |  abcd
2    |   x    |  xyz
2    |   y    |  xyz
2    |   z    |  xyz

@这实际上是一个结果,而不是一个表格。查询已经在递归CTE中完成,因此不能使用CTE。我之所以需要它,是因为我在使用CTE递归表时,试图跟踪以前递归层中的值。如果没有递归查询,这个问题就没有多大意义。您可以始终将查询结果输出到临时表中,并对其进行分组运算。引用递归版本指出,选择这种方法并不好:最好使用请始终解释您认为代码解决OP问题的原因。why比修复更有趣。为了更好地回答问题,您应该解释STRING_AGG函数的用途。
IF OBJECT_ID('dbo.fnConcatRowsPerGroup','FN') IS NOT NULL
DROP FUNCTION dbo.fnConcatRowsPerGroup
GO
CREATE FUNCTION dbo.fnConcatRowsPerGroup 
    (@grp as int) RETURNS VARCHAR(MAX)
AS 
BEGIN
    DECLARE @val AS VARCHAR(MAX)

    SELECT @val = COALESCE(@val,'')+val
    FROM tbl
    WHERE grp = @grp

    RETURN @val;
END
GO


select *, dbo.fnConcatRowsPerGroup(grp)
from tbl
grp  |   val  |  (No column name)
---------------------------------
1    |   a    |  abcd
1    |   b    |  abcd
1    |   c    |  abcd
1    |   d    |  abcd
2    |   x    |  xyz
2    |   y    |  xyz
2    |   z    |  xyz