在 Case 语句中执行 Count() 和 Avg()

Performing Count() and Avg() within a Case statement

我正在使用此 CASE 语句显示按年龄组分组的总访问次数和平均访问时长:

    CASE WHEN AgeCalcSort = 0 AND  AgeCalcSort <= 1 then (
        Count(VisitID),
        AVG(DATEDIFF(dd,StartDate,EndDate ))
        )
    WHEN AgeCalcSort >= 2 AND  AgeCalcSort <= 17 then (
                Count(VisitID),
        AVG(DATEDIFF(dd,StartDate,EndDate ))
        )
    WHEN AgeCalcSort >= 18 AND  AgeCalcSort <= 64 then (
                Count(VisitID),
        AVG(DATEDIFF(dd,StartDate,EndDate ))
        )
    WHEN AgeCalcSort >= 65 then (
                Count(VisitID),
        AVG(DATEDIFF(dd,StartDate,EndDate ))
        )
    END,

结果应如下所示:

Age 1 Count  Age 1 Avg LOS      Age 2 Count  Age 1 Avg LOS      Age 3 Count  Age 3 Avg LOS      Age 4 Count     Age 4 Avg LOS
5           5.3                 18          9.2                 20              12              0               0   

任何人都可以告诉我我做错了什么,或者有更好的方法来实现最终结果吗?提前致谢。

A case expression returns 单个值,然后您可以对其进行计数或取平均值。

无法从单个 case expression 生成多列输出。因此,您需要为每个想要的输出列使用一个 case 表达式,如下所示:

select
      COUNT(CASE WHEN AgeCalcSort = 0  AND  AgeCalcSort <= 1 then VisitID end)
    , AVG(CASE WHEN   AgeCalcSort = 0  AND  AgeCalcSort <= 1 then DATEDIFF(dd,StartDate,EndDate ) end)
    , COUNT(CASE WHEN AgeCalcSort = 2  AND  AgeCalcSort <= 17 then VisitID end)
    , AVG(CASE WHEN   AgeCalcSort = 2  AND  AgeCalcSort <= 17 then DATEDIFF(dd,StartDate,EndDate ) end)
    , COUNT(CASE WHEN AgeCalcSort = 18 AND  AgeCalcSort <= 64 then VisitID end)
    , AVG(CASE WHEN   AgeCalcSort = 18 AND  AgeCalcSort <= 64 then DATEDIFF(dd,StartDate,EndDate ) end)
    , COUNT(CASE WHEN AgeCalcSort = 65 then VisitID end)
    , AVG(CASE WHEN   AgeCalcSort = 65 then DATEDIFF(dd,StartDate,EndDate ) end)
from ...

备注:

  • 将每个 case 表达式放在相关的聚合函数中
  • count() 函数忽略 NULL,因此如果不满足 when 条件,计数将不会递增
  • 虽然 T-SQL 文档有时会使用不正确的术语 "case statement";例如完整的 select 查询是 "statement",而 "expressions" 计算为单个值,因此正确的术语是 case expression

您提到了两点:

1) Can anyone adivse what am I doing wrong

  • 您在查询中错误地使用了 CASE 表达式。
  • 当满足 CASE 语句中的某些条件时,您不能返回 2 列。
  • 根据 Microsoft 文档CASE 计算条件列表和 returns 多个可能的结果表达式之一。
  • 查看此 Microsoft 白皮书以进一步研究参考。 URL

2) a better way to achieve the end result

  • 可以通过多种方式实现这一目标。
  • 下面是其中一种简单的方法。试试下面的查询:

    SELECT
        SUM(CASE WHEN AgeCalcSort = 0 AND AgeCalcSort <= 1 THEN 1 ELSE 0 END) [Age 1 Count], 
        AVG(CASE WHEN AgeCalcSort = 0 AND AgeCalcSort <= 1 THEN DATEDIFF(DAY,StartDate,EndDate) ELSE NULL END) [Age 1 Avg LOS]
        SUM(CASE WHEN AgeCalcSort = 2 AND AgeCalcSort <= 17 THEN 1 ELSE 0 END) [Age 2 Count], 
        AVG(CASE WHEN AgeCalcSort = 2 AND AgeCalcSort <= 17 THEN DATEDIFF(DAY,StartDate,EndDate) ELSE NULL END) [Age 2 Avg LOS]
        SUM(CASE WHEN AgeCalcSort = 18 AND AgeCalcSort <= 64 THEN 1 ELSE 0 END) [Age 3 Count], 
        AVG(CASE WHEN AgeCalcSort = 18 AND AgeCalcSort <= 64 THEN DATEDIFF(DAY,StartDate,EndDate) ELSE NULL END) [Age 3 Avg LOS]
        SUM(CASE WHEN AgeCalcSort >= 65 THEN 1 ELSE 0 END) [Age 4 Count], 
        AVG(CASE WHEN AgeCalcSort >= 65 THEN DATEDIFF(DAY,StartDate,EndDate) ELSE NULL END) [Age 4 Avg LOS]
    FROM [YourTableName]
    

查询说明

  • 我已经通过使用 SUM 实现了计数,如果您查看任何计数逻辑,您会注意到它说当它满足条件 1 否则 0。稍后使用 SUM 求和。这样所有 1 最终都可以计数。
  • 对于平均值,您会注意到条件不满足,我使用 NULL,这是有意的,以避免错误的数学计算。
  • 在 TSQL 查询中,(2,4,NULL)AVG3,而 (2,4,0)AVG2。所以在你的情况下 NULL 将有助于避免混淆平均值。