按错误sql server分组

时间:2012-12-18 10:19:26

标签: sql sql-server

select 
    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 as CITY,
   count(*) as Total
from #tmptab1
group by CITY

我收到错误

  

Msg 207,Level 16,State 1,Line 12
  列名称“CITY”

无效

如何纠正这个?请帮忙。

3 个答案:

答案 0 :(得分:5)

您不能在GROUP BY子句中使用列别名。请参阅Conceptual Order of Evaluation of a Select Statement,您将看到这些条款按照此顺序进行(逻辑)评估:FROM, WHERE, GROUP BY, HAVING, SELECT, DISTINCT, UNION, ORDER BY

这并不是引擎执行操作的确切方式,但它是一个有用的启发式方法,可以实际理解为什么不能使用SELECT子句中GROUP BY语句中的内容 - - GROUP BY子句在逻辑上不可用,因为稍后会对其进行评估。

有几种解决方法:

  1. 重复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
    
  2. 使用派生表:

    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;
    
  3. 使用公用表表达式(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;
    
  4. 使用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;
    
  5. 由于您的表达式是确定性的,您可能只需执行GROUP BY location_id,但这不是正常情况,您不应该通过选择来绕过期望能够绕过正常的聚合分组逻辑单列,因为大多数情况下这样的CASE表达式会增加不确定的值。

    事实上,因为信息不仅是确定性的,而且是关于现实世界(而不是业务规则),我建议您不要在查询中对此信息进行编码!创建一个Location表并加入其中。将可更改的用户数据直接放入查询中并不是最佳做法 - 查询应该记录进程,而不是内容,以及如果添加新的location_id会怎样?使用它的所有查询都必须更改。此外,如果多个location_id可以引用同一个城市,则按location_id分组将无法正常工作。

答案 1 :(得分:2)

您不能在group by语句中使用别名 您将需要

中小组中的选择的整个部分
select 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 as CITY,count(1) as Total
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

对位置ID本身进行分组也可能有效

答案 2 :(得分:1)

关注(仅通过 group by location_id更改您的查询)适用于Sql-server 2008 or above(不确定如下)

select 
    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 as CITY,
   count(*) as Total
from #tmptab1
group by location_id --NOTE

Or您可以使用

select 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 as CITY, total
from (
    select location_id, count(*) total
    from #tmptab1 
    group by location_id ) A