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?
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.
Vous passez l'expression que vous voulez grouper plutôt que l'alias
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY LastName + ', ' + FirstName
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
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).
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
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.
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;
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
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)
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.
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?
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)
SELECT
CASE WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS 'FullName'
FROM customers GROUP BY 1`