获取在连接查询中组合的行

时间:2014-01-08 20:19:53

标签: sql sql-server

我正在处理查询:

USE SCRUMAPI2

DECLARE @userParam VARCHAR(100)
    ,@orgTeamPK VARCHAR(100)
    ,@statusParam VARCHAR(100)
    ,@search VARCHAR(100)
    ,@monthAgo VARCHAR(100)

SET @userParam = 'Amit Abc (abca)'
SET @orgTeamPK = '%'
SET @statusParam = '%'
SET @search = '%'
SET @monthAgo = '12/08/2013'

SELECT ROW_NUMBER() OVER (
        ORDER BY TSK.[Status] DESC
        ) AS 'RowNumber'
    ,PDT.[Name] AS Project
    ,(
        CASE 
            WHEN (
                    STY.KanBanProductId IS NOT NULL
                    AND STY.SprintId IS NULL
                    )
                THEN 'KanBan'
            WHEN (
                    STY.KanBanProductId IS NULL
                    AND STY.SprintId IS NOT NULL
                    )
                THEN 'Sprint'
            END
        ) AS ProjectType
    ,STY.[Number] StoryNumber
    ,STY.Title AS StoryTitle
    ,CONVERT(VARCHAR(20), STY.Effort) AS StoryPoints
    ,(
        SELECT SUM(OriginalEstimateHours)
        FROM Task TSK
        LEFT JOIN Story STU ON TSK.StoryId = STU.PK_Story
        LEFT JOIN Sprint SPT ON STU.SprintId = SPT.PK_Sprint
        LEFT JOIN Product PDT ON STU.ProductId = PDT.PK_Product
        LEFT JOIN [User] USR ON TSK.PointPerson = USR.DisplayName
        WHERE TSK.PointPerson LIKE @userParam
            AND (
                (
                    @orgTeamPK = '%'
                    AND (
                        USR.[OrganizationalTeamId] LIKE @orgTeamPK
                        OR USR.[OrganizationalTeamId] IS NULL
                        )
                    )
                OR (
                    @orgTeamPK <> '%'
                    AND (USR.[OrganizationalTeamId] LIKE @orgTeamPK)
                    )
                )
            AND STU.Number LIKE STY.Number
        ) AS StoryHoursEstimate
    ,ISNULL(SUM(DTH.[Hours]), 0) AS WorkHours
    ,'' AS Variance
    ,MAX(CASE 
            WHEN DTH.Hours != 0
                THEN DTH.ActivityDate
            END) AS LatestActivityDate
    ,(
        CASE 
            WHEN (TSK.[Status] = 'Not Started')
                THEN 'Active'
            WHEN (TSK.[Status] = 'In Progress')
                THEN 'Active'
            WHEN (TSK.[Status] = 'Impeded')
                THEN 'Active'
            WHEN (TSK.[Status] = 'Done')
                THEN 'Done'
            END
        ) AS [Status]
FROM Task TSK
LEFT JOIN DailyTaskHours DTH ON TSK.PK_Task = DTH.TaskId
LEFT JOIN Story STY ON TSK.StoryId = STY.PK_Story
LEFT JOIN Sprint SPT ON STY.SprintId = SPT.PK_Sprint
LEFT JOIN Product PDT ON STY.ProductId = PDT.PK_Product
LEFT JOIN [User] USR ON TSK.PointPerson = USR.DisplayName
WHERE TSK.PointPerson LIKE @userParam
    AND TSK.CreateDate >= CASE 
        WHEN TSK.[Status] = 'Done'
            THEN @monthAgo
        ELSE '1900-01-01'
        END
    AND TSK.[Status] LIKE @statusParam
    AND PDT.[Name] != 'Overhead Codes'
    AND (
        (
            @orgTeamPK = '%'
            AND (
                USR.[OrganizationalTeamId] LIKE @orgTeamPK
                OR USR.[OrganizationalTeamId] IS NULL
                )
            )
        OR (
            @orgTeamPK <> '%'
            AND (USR.[OrganizationalTeamId] LIKE @orgTeamPK)
            )
        )
    AND TSK.Deleted IS NULL
    AND (
        (
            STY.Number LIKE @search
            OR STY.Number IS NULL
            )
        OR (
            STY.Title LIKE @search
            OR STY.Title IS NULL
            )
        OR (
            TSK.NAME LIKE @search
            OR TSK.NAME IS NULL
            )
        )
GROUP BY LEN(STY.[Number])
    ,STY.[Number]
    ,TSK.[Status]
    ,STY.Title
    ,PDT.[Name]
    ,TSK.PointPerson
    ,TSK.CreateDate
    ,TSK.[Name]
    ,STY.KanBanProductId
    ,STY.SprintId
    ,TSK.OriginalEstimateHours
    ,STY.Effort
ORDER BY CASE TSK.[Status]
    WHEN 'Active'
        THEN 1
    WHEN 'Done'
        THEN 2
    END

以下是一些结果:

enter image description here

如图所示,有许多故事#PRO06-649。我希望将这些组合在一行上,在这一行上,每列当前的WorkHours将为该列求和。

我相信正在发生的事情之一就是我将WorkHours的总和高于我应该的水平。 我该如何做到这一点?

2 个答案:

答案 0 :(得分:2)

我不会解决您的整个查询,因为它是way more than necessary to demonstrate the problem,但我将提供一些有关如何删除重复项的一些信息。鉴于此数据:

CREATE TABLE dbo.mytable
(
  Project VARCHAR(255), 
  ProjectType VARCHAR(32),  
  StoryNumber CHAR(9),
  WorkHours DECIMAL(10,2),
  LastActivityDate DATETIME,
  [Status] VARCHAR(10)
);

INSERT dbo.mytable VALUES
('Procurement Project','Sprint','PRO06-262',0.00, NULL,'Active'),
('Procurement Project','Sprint','PRO06-649',5.00, '20140107','Active'),
('Other Systems',      'KanBan','MISCX-232',3.00, '20131230','Active'),
('Procurement Project','Sprint','PRO06-249',10.00,'20131219','Active'),
('Procurement Project','Sprint','PRO06-249',15.00,'20140103','Active'),
('Procurement Project','Sprint','PRO06-651',8.00, '20131213','Active');
GO

在猜测实际需要的结果时,这些是两种基本方法:

  1. 使用汇总和GROUP BY

    SELECT Project, ProjectType, StoryNumber, wh = SUM(WorkHours), 
      la = MAX(LastActivityDate), st = MIN([Status])
    FROM dbo.MyTable
    GROUP BY Project, ProjectType, StoryNumber;
    

    这种方法不是很灵活,因为你经常想要比较最新活动日期的状态,例如,没有好的方法来表达纯粹的聚合,而不会引入复杂的自连接和多次扫描。

  2. 使用CTE和窗口函数。

    ;WITH x AS 
    (
      SELECT Project, ProjectType, StoryNumber, 
        wh = SUM(WorkHours) OVER (PARTITION BY StoryNumber),
        rn = ROW_NUMBER() OVER (PARTITION BY StoryNumber ORDER BY LastActivityDate DESC), 
    la = LastActivityDate, 
        st = [Status]
      FROM dbo.MyTable
    )
    SELECT Project, ProjectType, StoryNumber, wh, la, st FROM x WHERE rn = 1;
    

    这种方法显然更灵活,但更冗长,更不直观。

  3. 您选择哪种方法取决于您的要求以及哪些方法产生的结果与您之后的结果相符(或者可以进行调整)。

答案 1 :(得分:0)

你真的需要行号吗?

此外,除非你准备在所有具有不同值的字段上使用聚合函数 - 比如工作时间,故事点等,否则我觉得有办法通过分组将多行缩小为一个。