【问题标题】:T-SQL : Avoid Subquery in favor of aggregationT-SQL :避免子查询以支持聚合
【发布时间】:2018-08-06 04:23:01
【问题描述】:

我已经使用 T-SQL 很长一段时间了,无法比我更好地进行聚合,这个例子将强调这一点。我敢肯定,可能有一些问题可以解决这个问题,但是,我不知道如何询问它,我也不知道如何更好地搜索它。

我有一个视图可以汇总每个团队成员的一些活动记录 Sample ActivityDetail ...

我需要做的其中一件事是获取给定时间段内所有团队成员的聚合(按成员的活动计数)。我发现使用本网站其他地方的串联黑客可以很容易地在每个成员/活动的专用行中获取每个活动总计

SELECT DISTINCT
      a.Member
    , a.Activity
    , COUNT(CONCAT(a.Member,a.Activity)) AS ActivityCount

FROM v_Activity a 
WHERE    a.Activity_Date > DATEADD(DAY,-7,GETDATE()) 
GROUP BY a.Member,a.Activity
ORDER BY a.Member

Sample ActivityTotals 但是我们在这里真正要寻找的是对此的更统一的表示。现在,我知道我可以像这样为每个 ActivityType 执行 COUNT(*) 子查询来到达那里

SELECT DISTINCT
      a.Member
    , (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Create' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Created
    , (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Update' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Updated
    , (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Document' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Documented
    , (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Deactivate' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Deactivated
    , (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Reactivate' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Reactivated

FROM v_cw_ConfigUpdateActivity a 
WHERE    a.Activity_Date > DATEADD(DAY,-7,GETDATE()) 
ORDER BY a.Member

这在获得我想要的输出方面做得不错(包括没有活动的零)。 Desired Output

但是(a)这是低效的 - 它已经表现不佳,并且(b)这只是尖叫聚合,但我显然太厚了,无法想出正确的方法来构建它以获得我正在寻找的东西。有什么帮助吗?

【问题讨论】:

    标签: tsql aggregation


    【解决方案1】:

    您可以使用 CASE 语句和 GROUP BY 来代替子查询。或者,您可以使用 PIVOT 来执行此操作。

    SELECT 
          a.Member
          SUM(CASE WHEM Activity = 'Create' THEN 1 ELSE 0 END) as Created,
          SUM(CASE WHEM Activity = 'Updated' THEN 1 ELSE 0 END) as Updated,
          SUM(CASE WHEM Activity = 'Documented' THEN 1 ELSE 0 END) as Documented,
          SUM(CASE WHEM Activity = 'Deactivated' THEN 1 ELSE 0 END) as Deactivated,
          SUM(CASE WHEM Activity = 'Reactivated' THEN 1 ELSE 0 END) as Reactivated    
    FROM v_cw_ConfigUpdateActivity a 
    WHERE    a.Activity_Date > DATEADD(DAY,-7,GETDATE()) 
    GROUP BY a.Member
    ORDER BY a.Member;
    

    我的 tsql 技能可能在这里显示他们的生锈,但这是对 PIVOT 版本的尝试:

    SELECT
        Member,
        Created,
        Updated,
        Documented,
        Deactivated,
        Reactivated
    FROM (SELECT Member, Activity FROM v_cw_ConfigUpdateActivity) as SourceTable
    PIVOT (COUNT(Activity) FOR Member IN (Created, Updated, Documented, Deactivated, Reactivated) as PivotTable
    

    【讨论】:

    • 尽管我很想了解 PIVOT 答案的优雅,但 SUM(CASE) 解决方案工作得很好,而且速度很快。谢谢你这么快的回答。
    猜你喜欢
    • 1970-01-01
    • 2021-09-13
    • 2019-06-13
    • 1970-01-01
    • 2020-03-07
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多