【问题标题】:Why does GROUP BY not work with created column in select statement?为什么 GROUP BY 不适用于 select 语句中创建的列?
【发布时间】:2021-08-23 19:25:56
【问题描述】:
我有以下脚本
SELECT
CASE
WHEN Grade < 4
THEN 'Fail'
WHEN Grade >=4 and Grade < 6
THEN 'C'
WHEN Grade >=6 and Grade < 8
THEN 'Ok'
ELSE 'Exc.'
END AS [Status],
COUNT(Grade) AS v
FROM
GradeList
GROUP BY
[Status]
它没有看到Status 列。不知道为什么,有什么问题
【问题讨论】:
标签:
sql
sql-server
tsql
sql-server-2008
【解决方案1】:
这就是 SQL Server(和 SQL)的定义方式。在SELECT 中定义的列别名在FROM、WHERE 或GROUP BY 子句中不可用。
对此有多种解决方案。我最喜欢的是使用APPLY,因为它定义了FROM 子句中的别名:
SELECT v.Status, COUNT(*) as v
FROM GradeList gl CROSS APPLY
(VALUES (CASE WHEN Grade < 4 THEN 'Fail'
WHEN Grade < 6 THEN 'C'
WHEN Grade < 8 THEN 'Ok'
ELSE 'Exc.'
END)
) v(Status)
GROUP BY v.Status;
请注意,这也简化了CASE 逻辑。返回第一个匹配条件,所以不需要BETWEEN。如果您想调整查询,这实际上使得添加和删除条件变得更加容易。
【解决方案2】:
SQL Server 以特定的逻辑顺序处理 SQL 语句。由于 SELECT 子句在 GROUP BY 子句之后,因此 GROUP BY 子句看不到列别名。
Read more on the logical processing order on MSDN
- 来自
- 开启
- 加入
- 在哪里
- 分组依据
- 使用多维数据集或使用汇总
- 有
- 选择
- 不同
- 订购人
- 顶部
您可以使用派生表或公用表表达式来解决这个问题。
SELECT Status, COUNT(Grade) AS v
FROM
(
SELECT
CASE
WHEN Grade < 4
THEN 'Fail'
WHEN Grade >=4 and Grade < 6
THEN 'C'
WHEN Grade >=6 and Grade < 8
THEN 'Ok'
ELSE 'Exc.'
END AS [Status],
Grade
FROM
GradeList
) AS g(Status,Grade)
GROUP BY
[Status]
;WITH cte_gradelist(Status,Grade) AS
(
SELECT
CASE
WHEN Grade < 4
THEN 'Fail'
WHEN Grade >=4 and Grade < 6
THEN 'C'
WHEN Grade >=6 and Grade < 8
THEN 'Ok'
ELSE 'Exc.'
END AS [Status],
Grade
FROM
GradeList
)
SELECT Status, COUNT(Grade) AS v
FROM cte_gradelist
GROUP BY
[Status]