CONCAT(专栏)OVER(PARTITION BY ...)?分组连接行而不对结果本身进行分组

时间:2012-08-19 03:12:00

标签: sql sql-server sql-server-2008 tsql string-aggregation

我需要一种方法来在一种窗口函数中对所有行(每组)进行串联,就像你可以做COUNT(*) OVER(PARTITION BY...)一样,每个组的所有行的聚合计数将在每个特定的组中重复。我需要类似的东西,但每个组中每个组的所有值的字符串连接都会重复。

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

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背景,所以不确定是否可以这样做。)


创建表:

CREATE TABLE tbl
    (grp int, val varchar(1));

INSERT INTO tbl
    (grp, val)
VALUES
    (1, 'a'),
    (1, 'b'),
    (1, 'c'),
    (1, 'd'),
    (2, 'x'),
    (2, 'y'),
    (2, 'z');

5 个答案:

答案 0 :(得分:1)

我尝试使用纯CTE方法:Which is the best way to form the string value using column from a Table with rows having same ID?认为它更快

但是基准测试说不然,最好使用CROSS APPLY的子查询(或XML PATH)结果,因为它们更快:Which is the best way to form the string value using column from a Table with rows having same ID?

答案 1 :(得分:1)

DECLARE @tbl TABLE
(
    grp INT
    ,val VARCHAR(1)
); 

BEGIN
 INSERT INTO @tbl(grp, val)
VALUES
    (1, 'a'),
    (1, 'b'),
    (1, 'c'),
    (1, 'd'),
    (2, 'x'),
    (2, 'y'),
    (2, 'z');
END;
----------- Your Required Query
SELECT  ST2.grp, 
SUBSTRING(
            (
                SELECT ','+ST1.val  AS [text()]
                FROM @tbl ST1
                WHERE ST1.grp = ST2.grp
                ORDER BY ST1.grp
                For XML PATH ('')
            ), 2, 1000
       ) groupcnct
FROM @tbl ST2

答案 2 :(得分:0)

您是否可以将您的内容放入选择中,或者您是否遇到同样的问题? (我替换了' 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

这对我有用 - 想知道这是否对你有用。

答案 3 :(得分:0)

在sql 2017中,您可以使用STRING_AGG功能:

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

答案 4 :(得分:0)

我知道这篇文章很老,但是以防万一,有人仍在想,您可以创建连接行值的标量函数。

SELECT
    SUM(TicketSales.TotalPrice) AS expr1
FROM 
    dbo.TicketSales,dbo.[Transaction]
WHERE 
    TicketSales.DeviceID = 'mapa001'
    AND SUM(TicketSales.TotalPrice) AS expr2
 FROM 
     dbo.TicketSales ,dbo.[Transaction]
 WHERE 
     TicketSales.DeviceID = 'mapa002'

这是我通过查询示例表获得的结果集:(您需要单击以下链接以查看我发布的图像,我没有足够的声誉来发布图像) Click here to see the image