web-dev-qa-db-fra.com

GROUP BY/confusion de la fonction d'agrégat dans SQL

J'ai besoin d'un peu d'aide pour arranger quelque chose, je sais que c'est une question facile très facile mais c'est quelque chose qui m'embrouille légèrement en SQL.

Cette requête SQL génère une erreur 'pas une expression GROUP BY' dans Oracle. Je comprends pourquoi, sachant qu’une fois que je groupe un attribut d’un tuple, je ne peux plus accéder à aucun autre attribut.

SELECT * 
FROM order_details 
GROUP BY order_no

Cependant celui-ci fonctionne

SELECT SUM(order_price)
FROM order_details
GROUP BY order_no

Pour concrétiser ce que je comprends à ce sujet ... En supposant qu'il y ait plusieurs tuples dans order_details pour chaque commande effectuée, une fois que j'ai groupé les tuples en fonction de order_no, je peux toujours accéder à l'attribut order_price pour chaque Tuple individuel du groupe, mais seulement en utilisant une fonction d'agrégat?

En d'autres termes, les fonctions d'agrégation utilisées dans la clause SELECT peuvent accéder au groupe pour afficher les attributs "masqués". Le simple fait d'utiliser "SELECT order_no" génère une erreur?

38
Chris

En SQL standard (mais pas MySQL), lorsque vous utilisez GROUP BY, vous devez répertorier toutes les colonnes de résultat qui ne sont pas agrégées dans la clause GROUP BY. Par conséquent, si order_details comporte 6 colonnes, vous devez répertorier ces 6 colonnes (par nom; vous ne pouvez pas utiliser * dans les clauses GROUP BY ou ORDER BY) dans la clause GROUP BY.

Vous pouvez aussi faire:

SELECT order_no, SUM(order_price)
  FROM order_details
 GROUP BY order_no;

Cela fonctionnera car toutes les colonnes non agrégées sont répertoriées dans la clause GROUP BY.

Vous pourriez faire quelque chose comme:

SELECT order_no, order_price, MAX(order_item)
  FROM order_details
 GROUP BY order_no, order_price;

Cette requête n'est pas vraiment significative (ou probablement pas), mais elle "fonctionnera". Il listera chaque combinaison de numéro de commande et de prix de commande, et indiquera le numéro de commande maximal (numéro) associé à ce prix. Si tous les articles d'une commande ont des prix distincts, vous vous retrouverez avec des groupes d'une ligne chacun. OTOH, s'il y a plusieurs articles dans la commande au même prix (disons 0,99 € chacun), il les regroupera et renverra le nombre maximal d'articles à ce prix. (Je suppose que la table a une clé primaire sur (order_no, order_item) où le premier élément de la commande a order_item = 1, le deuxième élément est 2, etc.)

41
Jonathan Leffler

Pour utiliser la clause group by, vous devez mentionner toutes les colonnes de l'instruction select in dans la clause group by, mais pas la colonne de la fonction d'agrégat.

Pour faire cela au lieu de groupe, vous pouvez utiliser partition par clause. Vous ne pouvez utiliser qu'un seul port pour grouper en tant que partition.

vous pouvez également le faire en tant que partition par 1

0
DoOrDie
SELECT * 
FROM order_details 
GROUP BY order_no

Dans la requête ci-dessus, vous sélectionnez toutes les colonnes car il génère une erreur et non pas un groupe similaire à .. Afin d'éviter de devoir mentionner toutes les colonnes dans l'instruction select. .

 SELECT * 
    FROM order_details 
    GROUP BY order_no,order_details,etc

etc cela signifie toutes les colonnes de la table order_details.

0
DoOrDie