[SQL] group by ou requête imbriquée ?

Bonjour,

Je suis en plein exo de requête SQL, chapitre finale sur les requêtes de sélection.

Je dois sélectionner dans la base les client ayant fais ou ayant en cours au moins 5 réservations, marqué “R” dans le champ Etat de la table Transaction. Le cours me semble demander la seconde methode, mais j’irais naturellement vers la première :

Requête n°1 :
select NumCl as [Numéro Client], NomCl as [Nom]
from Client C
where
(select count(*)
from Transaction T
where T.État = “R” and C.NumCl = T.NumCl) >= 5;

Requête n°2
select NomCl as [Nom du Client], count()
from Transaction T, Client C
where C.NumCl = T.NumCl and T.État = "R"
group by NumCl, NomCl
having count(
) >= 5

Ma question est assez simple : Est-ce que la première est juste ?
Je n’ai pas les moyens de tester (je n’ai pas de base à disposition), et bien que logiquement je n’y trouve rien à redire, ce ne serait pas la première fois que le lexique SQL irait contre ma logique.
Question subsidiaire : Je trouve la première plus élégante, enfin plus logique pour moi, mais elle fais faire deux requêtes. Laquelle serait la plus optimisée ? (dans l’optique où la première est juste). Si la mémoire utilisée est en fonction du produit cartésien induit par la requête, les deux seraient équivalentes ?

À vue de nez les deux ont l’air d’être correctes, mais la première devrait en principe être beaucoup moins performante (les sous-requêtes c’est des usines à gaz généralement moins bien gérées par les optimiseurs qu’un bête GROUP BY).

Toujours niveau performance : prends l’habitude d’utiliser des JOIN (INNER en l’occurrence) c’est également souvent beaucoup mieux optimisé qu’un WHERE équivalent.

D’accord, merci beaucoup pour ta réponse ! Très intéressante et ouverte sur de nouvelles pistes (je ne connais pas encore Join et Inner).

En fait un INNER JOIN permet de faire correspondre deux tables de la même manière qu’un WHERE. Ces deux requêtes sont équivalentes, mais la deuxième sera probablement mieux optimisée par le moteur SQL de ta base :

[code]SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=c

SELECT * FROM t1 INNER JOIN t2 ON t1.a=t2.a WHERE t1.b=c[/code]

Il y a aussi les variantes LEFT / RIGHT / FULL JOIN qui introduisent des sémantiques légèrement différentes (grosso modo, les champs d’une des tables sont remplacés par NULL lorsqu’un enregistrement de la deuxième table ne trouve pas de correspondance).

En bref :

INNER JOIN : uniquement les enregistrements communs, fonctionnellement équivalent à un WHERE
LEFT JOIN : tous les enregistrements de la table de gauche
RIGHT JOIN : tous les enregistrements de la table de droite
FULL JOIN : tous les enregistrements des deux tables