web-dev-qa-db-fra.com

Comment effectuer un GROUP BY sur une colonne avec alias dans MS-SQL Server?

J'essaie d'exécuter une action group by sur une colonne avec alias (exemple ci-dessous), mais je ne peux pas déterminer la syntaxe appropriée.

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

Quelle est la syntaxe correcte?


MODIFIER

En prolongeant la question (je ne m'attendais pas aux réponses que j'ai reçues), la solution serait-elle toujours valable pour une colonne avec 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.

51
Gavin Miller

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

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

C'est ce que je fais.

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

Cette technique s’applique directement à 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
32
Amy B

Malheureusement, vous ne pouvez pas faire référence à votre alias dans l'instruction GROUP BY, vous devrez réécrire la logique, aussi incroyable que cela puisse paraître.

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

Vous pouvez également placer la sélection dans une expression de sous-sélection ou une table commune, après quoi vous pouvez regrouper le nom de la colonne (plus un alias).

8
James Orr

Désolé, cela n’est pas possible avec MS SQL Server (possible 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 ca:

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

La requête ci-dessus est plus rapide, groupe les champs d’abord, puis calcule ces champs.

La requête suivante est plus lente (elle essaie de calculer d’abord l’expression sélectionnée, puis elle groupe les enregistrements en fonction de ce calcul). 

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

Ma conjecture est:

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

Oracle a une limitation similaire, ce qui est agaçant. Je suis curieux s'il existe une meilleure solution.

Pour répondre à la seconde partie de la question, cette limitation s’applique également à des expressions plus complexes telles que votre déclaration de cas. La meilleure suggestion que j'ai vue d'utiliser une sous-sélection pour nommer l'expression complexe.

3
Jon Ericson

Compte tenu de votre description du problème modifiée, je suggérerais d'utiliser COALESCE() à la place de cette expression lourde CASE:

SELECT FullName
FROM (
  SELECT COALESCE(LastName+', '+FirstName, FirstName) AS FullName
  FROM customers
) c
GROUP BY FullName;
3
Bill Karwin

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

SELECT       FullName
FROM         Customers
CROSS APPLY  (SELECT LastName + ', ' + FirstName AS FullName) Alias
GROUP BY     FullName
1
Ricardo
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éponse 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" donneraient tous deux "J Taylor".

Si vous voulez que votre sortie ait "J Taylor" deux fois (une pour chaque personne):

GROUP BY LastName, FirstName

Si, toutefois, vous vouliez juste une rangée de "J Taylor", vous voudriez:

GROUP BY LastName, LEFT(FirstName, 1)
1
MatBailie

Si vous voulez éviter que la requête ne soit gâchée deux fois dans votre requête, vous pouvez la placer dans une fonction définie par l'utilisateur.

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

0
JeffO

Dans l'ancien FoxPro (je ne l'utilise plus depuis la version 2.5), vous pouvez é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 mis en œuvre ailleurs? C'est un joli raccourci, mais je suppose que cela cause d'autres problèmes?

0
E.J. Brennan

Pour tous ceux qui se trouvent avec le problème suivant (regroupement en s'assurant que les valeurs nulles et nulles sont traitées comme des égaux) ...

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

(SQL Server se plaint de ne pas avoir inclus le champ Montant dans votre groupe ou fonction d'agrégation)

... souvenez-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
41st
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
Deepak Pathak