您不能在GROUP BY
子句中使用列别名。请参阅Select 语句的评估的概念顺序,您将在其中看到(逻辑上)按以下顺序评估子句:FROM, WHERE, GROUP BY, HAVING, SELECT, DISTINCT, UNION, ORDER BY
。
这并不是引擎执行操作的确切方式,但它是一种有用的启发式方法,可以有效地理解为什么不能使用子句中SELECT
语句中的某些GROUP BY
内容——它在逻辑上不适用于GROUP BY
子句后来评价。
有几种方法可以解决这个问题:
GROUP BY
重复子句中的整个表达式:
SELECT
City =
CASE location_id when 1 then 'DELHI' when 2 then 'AHMEDABAD'
when 4 then 'HYDERABAD' when 5 then 'KOLKATA' when 6 then 'BANGALORE'
when 7 then 'MUMBAI' when 8 then 'CHENNAI'
END,
Total = Count(*)
FROM #tmptab1
GROUP BY
CASE location_id when 1 then 'DELHI' when 2 then 'AHMEDABAD'
when 4 then 'HYDERABAD' when 5 then 'KOLKATA' when 6 then 'BANGALORE'
when 7 then 'MUMBAI' when 8 then 'CHENNAI'
END
使用派生表:
SELECT
City,
Total = Count(*)
FROM
(
SELECT
City =
CASE location_id when 1 then 'DELHI' when 2 then 'AHMEDABAD'
when 4 then 'HYDERABAD' when 5 then 'KOLKATA' when 6 then 'BANGALORE'
when 7 then 'MUMBAI' when 8 then 'CHENNAI'
END
FROM #tmptab1
) Cities
GROUP BY City;
使用公用表表达式 (CTE)、SQL Server 2005 及更高版本:
WITH Cities AS (
SELECT
City =
CASE location_id
when 1 then 'DELHI'
when 2 then 'AHMEDABAD'
when 4 then 'HYDERABAD'
when 5 then 'KOLKATA'
when 6 then 'BANGALORE'
when 7 then 'MUMBAI'
when 8 then 'CHENNAI'
END
FROM #tmptab1
)
SELECT
City,
Total = Count(*)
FROM Cities
GROUP BY City;
使用 CROSS APPLY、SQL Server 2005 及更高版本:
SELECT
City,
Total = Count(*)
FROM
#tmptab1
CROSS APPLY (
SELECT
City =
CASE location_id when 1 then 'DELHI' when 2 then 'AHMEDABAD'
when 4 then 'HYDERABAD' when 5 then 'KOLKATA' when 6 then 'BANGALORE'
when 7 then 'MUMBAI' when 8 then 'CHENNAI'
END
) C
GROUP BY City;
由于您的表达式是确定性的,因此您可以简单地做GROUP BY location_id
,但这不是正常情况,您不应该期望能够通过选择单个列来规避正常的聚合分组逻辑,因为大多数时间这样的 CASE 表达式增加了不确定的值。
事实上,因为信息不仅是确定性的,而且是关于现实世界的(而不是业务规则),我建议您不要在查询中编码这些信息!创建一个Location
表并加入它。将可更改的用户数据直接放入查询中并不是最佳实践——查询应该记录过程,而不是内容,如果添加新的 location_id 会怎样?所有使用它的查询都必须改变。location_id
此外,如果多个location_id
可以引用同一个城市,分组依据将无法正常工作。