在 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)
的 AVG
是 3
,而 (2,4,0)
的 AVG
是 2
。所以在你的情况下 NULL
将有助于避免混淆平均值。
我正在使用此 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)
的AVG
是3
,而(2,4,0)
的AVG
是2
。所以在你的情况下NULL
将有助于避免混淆平均值。