【问题标题】:TSQL Multiple count using same table with different JOIN使用具有不同 JOIN 的同一表的 TSQL 多次计数
【发布时间】:2014-08-28 22:30:22
【问题描述】:

我有一个奇怪的情况,不太确定如何处理它。

我有 2 个单独的表:

表A是提交

id
submitterQID
nomineeQID
story

表 B 是员工

QID
Name
Department

我正在尝试获取按部门分组的提交总数以及提名总数。

这就是我的存储过程的样子:

BEGIN
                SELECT   TOP 50 count(A.[nomineeQID]) AS totalNominations,
                                count(A.[subQID]) AS totalSubmissions,
                                B.[DepartmentDesc] AS department
                FROM     empowermentSubmissions AS A
                JOIN empTable AS B
                ON B.[qid] = A.[nomineeQID]
                WHERE A.[statusID] = 3
                AND A.[locationID] = @locale
                GROUP BY B.[Department]
                ORDER BY totalNominations DESC
                FOR      XML PATH ('data'), TYPE, ELEMENTS, ROOT ('root');
            END

这个问题是 JOIN 仅由 nomineeQID 加入,而不是 subQID

我正在寻找的最终结果是:

部门客户服务有 25 个提交和 90 个提名

按两个计数的总和排序...

我尝试在 subQID 上再次加入 JOIN,但被告知我不能在同一张桌子上加入两次。

有没有更简单的方法来做到这一点?

【问题讨论】:

    标签: sql sql-server sql-server-2008 stored-procedures join


    【解决方案1】:

    在这种情况下,您需要彼此独立地收集计数。当两个左连接都满足连接条件时,使用两个左连接将导致某些行在第一个左连接中被计算两次。您可以使用相关子查询或外部应用来解决您的场景,该应用收集不同标准的计数。我没有在这里提供COUNT(CASE ... ) 选项,因为您在数据中没有非此即彼的情况,您有两个外键到employees 表。所以,设置示例数据:

    declare @empowermentSubmissions table (submissionID int primary key identity(1,1), submissionDate datetime, nomineeQID INT, submitterQID INT, statusID INT, locationID INT)
    declare @empTable table (QID int primary key identity(1,1), AreaDesc varchar(10), DepartmentDesc varchar(20))
    declare @locale INT = 0
    declare @n int = 1
    
    while @n < 50
    begin
        insert into @empTable (AreaDesc, DepartmentDesc) values ('Area ' + cast((@n % 2)+1 as varchar(1)), 'Department ' + cast((@n % 4)+1 as varchar(1)))
        set @n = @n + 1
    end
    set @n = 1
    while @n < 500
    begin
        insert into @empowermentSubmissions (submissionDate, nomineeQID, submitterQID, StatusID, locationID) values (dateadd(dd,-(cast(rand()*600 as int)),getdate()), (select top 1 QID from @empTable order by newid()), (select top 1 QID from @empTable order by newid()), 3 + (@n % 2) - (@n % 3), (@n % 2) )
        set @n = @n + 1
    end
    

    现在是OUTER APPLY 选项:

    SELECT TOP 50 E.DepartmentDesc, SUM(N.Nominations) Nominations, SUM(S.TotalSubmissions) TotalSubmissions
    FROM @empTable E
        OUTER APPLY (
            SELECT COUNT(submissionID) Nominations
            FROM @empowermentSubmissions A
            WHERE A.statusID = 3
                AND A.nomineeQID = E.QID
                AND A.locationID = @locale
        ) N
        OUTER APPLY (
            SELECT COUNT(submissionID) TotalSubmissions
            FROM @empowermentSubmissions A
            WHERE A.statusID = 3
                AND A.submitterQID = E.QID
                AND A.locationID = @locale
        ) S
    GROUP BY E.DepartmentDesc
    ORDER BY SUM(Nominations) + SUM(TotalSubmissions) DESC
    

    【讨论】:

    • 我遇到的一个大问题是这方面的表现。似乎它正在查看整个employeeTable,然后当它在提交表中找到某些内容时,它会执行它的工作。 empTable 包含超过 10k 条记录,所以我想知道这是否会成为问题。当我在我的桌子上运行代码时,它试图返回每个员工的数据。
    • 啊,我错过了部门。无论如何,它必须迭代员工记录以按部门分组,并获得提名/提交计数,但我确实对此犯了错误。查看我的编辑。
    • 关于性能,如果 powermentSubmissions.nomineeQID 和 powermentSubmissions.locationID 在索引中配对,并且 powermentSubmissions.submitterQID 和 powermentSubmissions.locationID 在索引中配对,这应该非常快。 10K 条记录应该不是问题。
    猜你喜欢
    • 1970-01-01
    • 2013-05-28
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-10
    相关资源
    最近更新 更多