SQL Server连接GROUP BY

时间:2012-05-05 12:32:42

标签: sql sql-server

我有一个看起来像这样的查询

SELECT J.JobID,T.Title FROM JobsTagMap J
Left Join Tags T
ON J.TagID=T.TagID

返回以下数据集(简化,JobID实际上是UniqueIdentifier)

JobID    Title
1        Tag1
1        Tag2
2        Tag2
2        Tag5
2        Tag9

现在,我想通过JobID列对其进行分组并连接Title,所以结果如下

JobID    Title
1        Tag1,Tag2
2        Tag2,Tag5,Tag9

我该怎么做?

3 个答案:

答案 0 :(得分:10)

如果您使用的是sql server 2005+。然后你可以这样做:

SELECT 
    JobsTagMap.JobID,
    STUFF
    (
        (
            SELECT 
                ',' +Title
            FROM
                Tags
            WHERE
                Tags.TagID=JobsTagMap.TagID
            FOR XML PATH('')
        )
    ,1,1,'') AS Title
FROM JobsTagMap

修改

因为您没有向我们展示表结构和不同表中的数据。这有点难以理解。所以我假设你的表结构看起来像这样:

CREATE TABLE JobsTagMap
(
    JobID INT,
    TagID INT
)

CREATE TABLE Tags
(
    TagID INT,
    Title VARCHAR(100)
)

有了这些数据:

INSERT INTO JobsTagMap
VALUES(1,1),(1,2),(2,2),(2,4),(2,5)

INSERT INTO Tags
VALUES(1,'Tag1'),(2,'Tag2'),(3,'Tag2'),(4,'Tag5'),(5,'Tag9')

如果您获得的是您所显示的数据JobID不能是唯一的。您可能在某个地方有一个Job表,它是唯一的。如果您只想使用这些表格,那么您需要执行以下操作:

;WITH CTE
AS
(
    SELECT
        ROW_NUMBER() OVER(PARTITION BY JobID ORDER BY JobID) AS RowNbr,
        JobsTagMap.*
    FROM
        JobsTagMap
)
SELECT
    *,
    STUFF
    (
        (
            SELECT 
                ',' +Title
            FROM
                Tags
                JOIN JobsTagMap
                    ON Tags.TagID=JobsTagMap.TagID
            WHERE
                JobsTagMap.JobID=CTE.JobID
            FOR XML PATH('')
        )
    ,1,1,'') AS Title
FROM
    CTE
WHERE
    CTE.RowNbr=1

这会得到这个结果:

1   1   1   Tag1,Tag2
1   2   2   Tag2,Tag5,Tag9

因此,将来始终会显示表格结构以及数据。那会给你更好的答案

答案 1 :(得分:1)

我正是使用标量函数。有一些纯粹主义者认为解密应该永远不会使用基于行的操作,但是嘿这是有效的,如果你只返回几行,那么响应时间就可以了。

CREATE FUNCTION [dbo].[JoinMVText]

(

  @sID int,

  @fieldID tinyint

)

RETURNS VARCHAR(MAX)

AS 

BEGIN

   DECLARE @MVtextList varchar(max)

   SELECT @MVtextList = COALESCE(@MVtextList + '; ', '') + docMVtext.value

   FROM docMVtext with (nolock) 

   WHERE docMVtext.sID = @sID and fieldID = @fieldID

   RETURN @MVtextList

END

答案 2 :(得分:0)

我遇到了与您同样的问题,并且找出了解决慢速子选择的方法。

使用 GROUP BY

(70500 rows affected)

 SQL Server Execution Times:
   CPU time = 94 ms,  elapsed time = 833 ms.

使用子选择

(70500 rows affected)

 SQL Server Execution Times:
   CPU time = 1469 ms,  elapsed time = 2323 ms.

子选择要慢4倍以上...

这是解决方案:

SELECT 
    J.JobID,
    STRING_AGG(ISNULL(T.Title, ''), ',') as Title
FROM JobsTagMap J
LEFT JOIN Tags T ON J.TagID = T.TagID
GROUP BY J.JobID;

让我知道是否有些不清楚:)