2009-01-30 7 views
43

J'essaie d'effectuer un groupe par action sur une colonne aliasée (exemple ci-dessous), mais ne peut pas déterminer la syntaxe correcte.Comment effectuer un GROUP BY sur une colonne avec alias dans MS-SQL Server?

SELECT  LastName + ', ' + FirstName AS 'FullName' 
FROM   customers 
GROUP BY  'FullName' 

Quelle est la bonne syntaxe?


EDIT

L'extension de la question plus loin (je ne m'y attendais pas les réponses que j'avais reçues) serait la solution pour appliquer encore une colonne aliasé CASEed?

SELECT  
    CASE 
     WHEN LastName IS NULL THEN FirstName 
     WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName 
    END AS 'FullName' 
FROM   customers 
GROUP BY  
    LastName, FirstName 

Et la réponse est oui cela s'applique toujours.

Répondre

53

Vous passez l'expression que vous voulez groupe plutôt que par l'alias

SELECT  LastName + ', ' + FirstName AS 'FullName' 
FROM   customers 
GROUP BY  LastName + ', ' + FirstName 
+0

pas besoin de mettre le '' dans GROUP BY. le groupement peut être indiqué avec ou sans ',', vous pouvez même éviter la faute de frappe (par exemple ','), donc aucune erreur de requête invalide ne peut survenir –

+0

Faites-vous référence à ma suggestion, ou à la suppression du '+,' du groupe par l'expression? – cmsjr

+0

supprimez simplement le ',' dans la clause group by.cela fonctionne: sélectionnez le nom + ',' + prénom comme le nom complet de la personne grouper par nom, prénom –

7

Malheureusement, vous ne pouvez pas référencer votre alias dans la clause GROUP BY, vous devrez écrire à nouveau la logique, incroyable comme cela semble.

SELECT  LastName + ', ' + FirstName AS 'FullName' 
FROM   customers 
GROUP BY  LastName + ', ' + FirstName 

Alternativement, vous pouvez mettre la sélection dans une sous-sélection ou l'expression de table commune, après quoi vous pourriez groupe sur le nom de la colonne

3

Je suppose (plus un alias.):

SELECT  LastName + ', ' + FirstName AS 'FullName' 
FROM   customers 
GROUP BY  LastName + ', ' + FirstName 

Oracle a une limitation similaire, ce qui est ennuyeux. Je suis curieux de savoir s'il existe une meilleure solution.

Pour répondre à la deuxième partie de la question, cette limitation s'applique également aux expressions plus complexes telles que votre instruction case. La meilleure suggestion que je l'ai vu pour utiliser un sous-select pour nommer l'expression complexe.

+1

pas besoin de mettre le ',' dans GROUP BY. le groupement peut être indiqué avec ou sans ',', vous pouvez même éviter la faute de frappe (par exemple ','), donc aucune erreur de requête invalide ne peut survenir –

+0

True. Mais je trouve ce qui précède un peu plus clair. Votre solution de sous-sélection est encore plus claire, évidemment. ;-) –

+0

Vous avez besoin de la virgule pour éviter le cas de bordure 'ab, c' vs 'a, bc'. Ils rouleraient le même sans la virgule. –

26

C'est ce que je fais.

SELECT FullName 
FROM 
(
    SELECT LastName + ', ' + FirstName AS FullName 
    FROM customers 
) as sub 
GROUP BY FullName 

Cette technique applique d'une manière simple à votre scénario "modifier":

SELECT FullName 
FROM 
(
    SELECT 
    CASE 
     WHEN LastName IS NULL THEN FirstName 
     WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName 
    END AS FullName 
    FROM customers 
) as sub 
GROUP BY FullName 
5

Désolé, cela est impossible avec MS SQL Server (possible mais avec PostgreSQL):

select lastname + ', ' + firstname as fullname 
from person 
group by fullname 

Sinon, utilisez simplement ceci:

select x.fullname 
from 
(
    select lastname + ', ' + firstname as fullname 
    from person 
) as x 
group by x.fullname 

Ou ceci:

select lastname + ', ' + firstname as fullname 
from person 
group by lastname, firstname -- no need to put the ', ' 

La requête ci-dessus est plus rapide, regroupe les champs d'abord, puis ces champs calcul.

La requête suivante est plus lente (elle essaie de de calculer d'abord l'expression select, puis elle regroupe les enregistrements basés sur ce calcul).

select lastname + ', ' + firstname as fullname 
from person 
group by lastname + ', ' + firstname 
+0

FWIW vous pouvez également utiliser des alias de colonne dans GROUP BY dans MySQL. Mais strictement, il n'est pas supporté par le standard SQL. –

0

Dans l'ancien FoxPro (je ne l'ai pas utilisé depuis la version 2.5), vous pourriez écrire quelque chose comme ceci:

SELECT  LastName + ', ' + FirstName AS 'FullName', Birthday, Title 
FROM   customers 
GROUP BY  1,3,2 

J'ai vraiment aimé cette syntaxe. Pourquoi n'est-il pas implémenté ailleurs? C'est un raccourci sympa, mais je suppose que ça pose d'autres problèmes?

+3

Ceci est encore possible mais est généralement mal vu. Les développeurs finissent par ajouter une nouvelle colonne au milieu de votre liste de colonnes, puis modifient de manière inattendue les critères de regroupement. C'est une de ces choses qui fonctionne mais est considérée comme une mauvaise forme, comme mettre select * dans vos requêtes. –

+0

@ShaneDelmore Je sais que c'est un fil ancien, mais quels moteurs supportent cette syntaxe aujourd'hui? Quel est le terme pour cette utilisation? Pouvez-vous utiliser de tels non-alias dans d'autres clauses (par exemple 'WHERE' /' HAVING')? Si oui, comment le moteur sait-il distinguer le champ # 2 de l'entier 2 (par exemple 'WHERE 2 n'est pas NULL' /' HAVING 2 = 1') – mpag

3

Compte tenu de la description du problème édité, je suggère d'utiliser COALESCE() au lieu de cette expression CASE difficile à manier:

SELECT FullName 
FROM (
    SELECT COALESCE(LastName+', '+FirstName, FirstName) AS FullName 
    FROM customers 
) c 
GROUP BY FullName; 
0
SELECT  
    CASE 
     WHEN LastName IS NULL THEN FirstName 
     WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName 
    END AS 'FullName' 
FROM 
    customers 
GROUP BY  
    LastName, 
    FirstName 

Cela fonctionne parce que la formule que vous utilisez (l'instruction CASE) ne peut jamais donner la même répondre pour deux entrées différentes.

Ce n'est pas le cas si vous avez utilisé quelque chose comme:

LEFT(FirstName, 1) + ' ' + LastName 

Dans un tel cas « James Taylor » et « John Taylor » serait à la fois résultat dans « J Taylor ».

Si vous vouliez que votre sortie pour avoir « J Taylor » deux fois (une pour chaque personne):

GROUP BY LastName, FirstName 

Cependant, si vous vouliez juste une rangée de « J Taylor » que vous voudriez:

GROUP BY LastName, LEFT(FirstName, 1) 
0

Si vous voulez éviter que le désordre de l'instruction de cas ne soit dans votre requête deux fois, vous voudrez peut-être le placer dans une fonction définie par l'utilisateur.

Désolé, mais SQL Server ne restituerait pas l'ensemble de données avant la clause Group By afin que l'alias de colonne ne soit pas disponible. Vous pouvez l'utiliser dans l'ordre par.

0
SELECT 
CASE WHEN LastName IS NULL THEN FirstName   
    WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName  
END AS 'FullName' 
FROM customers GROUP BY 1` 
+0

Consultez cette réponse http://stackoverflow.com/a/ 497268/249353 pour voir pourquoi ce mode de regroupement n'est pas préférable. – Josien

+1

Demandé il y a 3 ans, accepté la réponse avec 14 upvotes il y a 3 ans aussi. – Yaroslav

0

Pour toute personne qui se retrouve avec le problème suivant (regroupement en assurant zéro et les valeurs nulles sont traités comme des égaux) ...

SELECT AccountNumber, Amount AS MyAlias 
FROM Transactions 
GROUP BY AccountNumber, ISNULL(Amount, 0) 

(Ie SQL Server se plaint que vous avez pas inclus le champ Montant de votre groupe ou par fonction d'agrégation)

... Rappelez-vous de placer exactement la même fonction dans votre SELECT ...

SELECT AccountNumber, ISNULL(Amount, 0) AS MyAlias 
FROM Transactions 
GROUP BY AccountNumber, ISNULL(Amount, 0) 
0

Vous pouvez utiliser CROSS APPLY pour créer un alias et l'utiliser dans la clause GROUP BY, comme ceci:

SELECT  FullName 
FROM   Customers 
CROSS APPLY (SELECT LastName + ', ' + FirstName AS FullName) Alias 
GROUP BY  FullName