2012-12-18 1 views
0
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 

J'obtiens l'erreurgroupe par le serveur SQL d'erreur

Msg 207, niveau 16, état 1, ligne 12
nom de colonne non valide 'CITY'

Comment rectifier ce ? S'il vous plaît aider.

Répondre

5

Vous ne pouvez pas utiliser la colonne alias dans les clauses GROUP BY. S'il vous plaît voir Conceptual Order of Evaluation of a Select Statement, où vous verrez que les clauses sont (logiquement) évaluées dans cet ordre: FROM, WHERE, GROUP BY, HAVING, SELECT, DISTINCT, UNION, ORDER BY.

Ce n'est pas exactement comment le moteur effectue l'opération, mais c'est une heuristique utile pour une compréhension pratique solide de la raison pour laquelle vous ne pouvez pas utiliser quelque chose de l'instruction SELECT dans la clause GROUP BY - il n'est pas logiquement disponible à la clause GROUP BY car il est évalué plus tard.

Il y a plusieurs façons de contourner cela:

  1. Répétez l'expression entière dans la clause 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. Utilisez une table dérivée:

    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. Utilisez un Expression de table commune (CTE), SQL Server 2005 et plus:

    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. Utilisez CROSS APPLY, SQL Server 2005 et plus:

    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; 
    

Étant donné que votre expression est déterministe, il est possible que vous pouvez simplement faire GROUP BY location_id, mais ce n'est pas normal Dans ce cas, vous ne devriez pas vous attendre à pouvoir contourner la logique de regroupement d'agrégat normale en sélectionnant une seule colonne, car la plupart du temps une telle expression CASE ajoute une valeur qui n'est pas déterministe. En fait, parce que l'information n'est pas seulement déterministe mais concerne le monde réel (plutôt que les règles métier), je vous recommande de ne pas encoder cette information dans votre requête! Créez une table Location et rejoignez-la. Il n'est pas recommandé de mettre directement les données utilisateur modifiables dans les requêtes - les requêtes sont censées enregistrer le processus, pas le contenu, et que se passe-t-il si vous ajoutez un nouvel ID de lieu? Toutes les requêtes qui l'utilisent devront changer. De plus, le regroupement par location_id ne fonctionnera pas correctement si plus d'un location_id peut faire référence à la même ville.

+0

merci pour l'explication détaillée, vraiment appréciée .. –

2

vous ne pouvez pas aliasses d'utilisation dans le groupe par déclaration dont vous aurez besoin toute la partie de la sélection de votre groupe par

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 

regroupement sur lui-même LOCATION_ID pourrait aussi travailler

+0

... Merci regroupement sur location_id a fonctionné!. –

+1

vous êtes les bienvenus, dans certains cas, le résultat peut différer de la valeur d'origine. si 1 et 2 ont donné 'DELHI' vous auriez eu besoin de la déclaration entière ou les résultats auraient été faux – ufosnowcat

1

Suite (changer votre requête juste engroup by location_id) fonctionne sur Sql-server 2008 or above (pas sûr ci-dessous)

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 vous pouvez utiliser

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