web-dev-qa-db-fra.com

Pourquoi les caractères génériques dans les instructions GROUP BY ne fonctionnent-ils pas?

J'essaie de faire fonctionner l'instruction SQL suivante, mais j'obtiens une erreur de syntaxe:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.*

Ici, A est un tableau large avec 40 colonnes et je voudrais éviter de lister chaque nom de colonne dans la clause GROUP BY si possible. J'ai beaucoup de ces tables sur lesquelles je dois exécuter une requête similaire, donc je vais devoir écrire une procédure stockée. Quelle est la meilleure façon d'aborder cela?

J'utilise MS SQL Server 2008.

29
Anonymous Maximus

GROUP BY A.* n'est pas autorisé dans SQL.

Vous pouvez contourner cela en utilisant une sous-requête dans laquelle vous vous regroupez, puis rejoignez:

SELECT A.*, COALESCE(B.cnt, 0) AS Count_B_Foo
FROM TABLE1 AS A
  LEFT JOIN 
      ( SELECT FKey, COUNT(foo) AS cnt
        FROM TABLE2 
        GROUP BY FKey
      ) AS B 
    ON A.PKey = B.FKey ;

Il existe une fonctionnalité dans la norme SQL-2003 pour autoriser dans la liste SELECT, les colonnes qui ne sont pas dans le GROUP BY list, tant qu'ils en dépendent fonctionnellement. Si cette fonctionnalité avait été implémentée dans SQL-Server, votre requête aurait pu être écrite comme suit:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.pk                          --- the Primary Key of table A

Malheureusement, cette fonctionnalité n'a pas encore été implémentée, pas même dans la version SQL-Server 2012 - et dans aucun autre SGBD pour autant que je sache. À l'exception de MySQL qui l'a mais de manière inadéquate (insuffisamment comme: la requête ci-dessus fonctionnera mais le moteur ne vérifiera pas la dépendance fonctionnelle et d'autres requêtes mal écrites afficheront des résultats faux et semi-aléatoires).

Comme @ Mark Byers nous a informés dans un commentaire, PostgreSQL 9.1 a ajouté une nouvelle fonctionnalité conçu pour Cet objectif. Elle est plus restrictive que l'implémentation de MySQL.

32
ypercubeᵀᴹ

En plus de la solution de contournement de @ ypercube, la "saisie" n'est jamais une excuse pour utiliser SELECT *. J'ai écrit à ce sujet ici , et même avec la solution de contournement, je pense que votre liste SELECT devrait toujours inclure les noms des colonnes - même s'il existe un nombre massif comme 40.

Pour faire court, vous pouvez éviter de taper ces grandes listes en cliquant et en faisant glisser le nœud Colonnes de l'objet dans l'Explorateur d'objets vers votre fenêtre de requête. La capture d'écran montre une vue mais la même chose peut être faite pour une table.

enter image description here

Mais si vous voulez en savoir plus sur toutes les raisons pourquoi vous devez vous soumettre à cet énorme niveau d'effort de faire glisser un élément de quelques centimètres, veuillez lire mon article . :-)

24
Aaron Bertrand