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