jointure dans le where ou dans le from - SQL/NoSQL - Programmation
Marsh Posté le 03-09-2007 à 10:04:37
question d'habitude et de préférence.
perso, j'ai longtemps préféré les jointures dans le where, car je les trouvais plus lisible.
jusqu'au jour où je me suis heurté à des cas à la con, impossibles à écrires avec ce système. maintenant je préfère avec les join.
dans tous les cas, il m'arrive de mélanger les deux, genre faire un "inner join" sur une sous-requête, je trouve ça passablement illisible, donc je faire mon join dans le where.
habitue toi aux deux syntaxe, et préfère celle du from afin de ne pas être bloqué je jour où tu devras faire des full outer join et des left/right outer join en cascade.
cependant, n'oublie pas l'autre pour autant, certains sgbd ont du mal avec les jointures dans le from (oracle jusqu'à la 9i par exemple si je ne m'abuse)
Marsh Posté le 03-09-2007 à 10:27:52
JOINS FTW!!!
Plus sérieusement je suis d'accord avec Magic, c'est une question d'habitude.
Perso je peux pas supporter les clauses de jointure dans les wheres. Je trouve ça illisible et dangereux ( c'est le meilleur moyen de transformer un outer en inner sans s'en apercevoir).
Mais bon les goûts et les couleurs
Marsh Posté le 03-09-2007 à 12:28:07
merci pour ces précisions,
donc cela ce vaut si j'ai bien compris juste une question d'habitude.
par contre c'est quoi ? full outer
Marsh Posté le 03-09-2007 à 14:17:25
Les jointures expliquées :
http://forum.hardware.fr/hfr/Progr [...] m#t1495691
Marsh Posté le 03-09-2007 à 20:03:47
merci de ce lien très utile, je vais jeter un oeil car apparement je pensait que toutes les jointures donnait le même résultat, mais apparament c'est pas le cas.
j'ai une deuxième question dans le cas d'utilisation de fonction dans le select comme avg, sum, count etc.
est ce que dans le cas d'une comparaison d'un element utilisant une fonction on peux le faire dans le where ou doit-on passer par une clausz group by et having
Marsh Posté le 04-09-2007 à 08:10:24
ça dépend des fonctions.
les fonctions d'agrégat telles que avg, sum ou count nécessivent effectivement d'utiliser having et group by. on ne peut pas les trouver dans une clause where.
mais des fonctions de valeur telles que les fonctions de cast, formattage de chaîne, etc. s'utilisent comme n'importe quel champ.
Code :
|
Marsh Posté le 04-09-2007 à 12:49:09
par contre il me semble que le group by doit comporter tout les champs du select, si je ne me trompes pas.
Marsh Posté le 04-09-2007 à 13:19:08
et puis surtout dans la requete de magic tous les champs du select sont dans le group by, Moyenne étant un alias de avg(note).
Marsh Posté le 04-09-2007 à 13:28:50
si j'ai dit ça c'est que j'avais fais un test et quand ne stipulant pas tout les champs du select dans le where cela n'avait pas fonctionner, mais peut être que j'avais une erreur ailleurs
Marsh Posté le 04-09-2007 à 13:35:25
en fait ça dépend des SGBDs, mais généralement c'est pas nécessaire.
Marsh Posté le 04-09-2007 à 14:26:50
La norme SQL stipule que le GROUP BY doit contenir AU MOINS TOUS les champs (y compris les calculs) SAUF les valeurs faisant l'objet d'une fonction d'agréga.
MySQL est un peu bourrin, il accepte qu'on ne les mette pas tous les champs. Dans ce cas, il n'y a aucun moyen de prévoir "à coup sûr" ce qu'il va faire, ceci dépendant uniquement de son interprétation personnelle : génération des regroupements manquants, récupèration de la première valeur des champs non regroupés, etc.
Il vaut donc mieux suivre ce que dit la norme, dans un souci de portabilité, et de garantie du résultat.
En fait, une fonction d'agrégat, c'est assez simple à comprendre comme ça marche : ça va faire un traîtement sur un group donné.
Par exemple :
Code :
|
=> Ca va compter les lignes du groupe de lignes formée par l'ensemble des lignes de "matable".
Dans un cas où on a d'autres champs :
Code :
|
Le count porte sur quoi ? Sur l'ensemble des lignes de la table utilisateur ? Sur chaque valeur différente de "nom" ? Aucune idée.
Pour cette raison, un SGBD classique va émettre une erreur et s'arrêter : c'est pas à lui de prendre ce genre de décisions.
La requête correcte sera donc :
Code :
|
=> Pour chaque groupe identifié par une valeur unique de "nom", on a le nombre d'utilisateurs.
Mais que dire dans un cas de ce genre :
Table "produit" :
|
Je veux connaître le prix moyen pour chaque volume de produit.
Code :
|
Réfléchissons...
Si je fais un "group by largeur, longueur, hauteur", puisque aucun de ces tuples n'est en double, je vais avoir 3 lignes. Pourtant, dans la colonne "volume", j'aurais bien 2 fois la même valeur (les produits A et B ont le même volume).
Le group by doit donc porter sur le calcul, et non les champs ! Ceci dit, on a le droit de l'écrire sous cette forme, car le regroupement reste valide, puisqu'on a énuméré la liste de tous les champs non agrégés.
Code :
|
Enfin, le group by ne peut contenir d'alias. Il doit comporter l'expression exacte.
Ainsi ceci n'est pas valide en SQL, même si certains SGBD le supportent :
Code :
|
Marsh Posté le 05-09-2007 à 09:22:38
MagicBuzz a écrit :
|
Tiens, je savais pas ça. Sur Mysql, ça marche nickel et avec cette solution, j'aurais eu tendance à penser que les perfs sont meilleurs car le sgbd n'a pas besoin de recalculer l'expression spécifiée dans le group by
Marsh Posté le 05-09-2007 à 09:40:38
Si l'expression est la même, je doute qu'il la réévalue.
Par contre, je n'ai effectivement jamais pigé pourquoi on ne doit pas mettre d'alias, parceque le group by est de toute façon une requête plus ou moins post processing, c'est à dire qu'il ne peut être calculé qu'une fois l'ensemble des lignes trouvées et évaluées. Donc comme le order by, je ne vois pas pourquoi on ne peut pas mettre d'alias.
C'est du moins le cas avec Oracle, et si de tête, SQL Server supporte l'utilisation d'un alias, il n'est spécifié null part dans la doc qu'on peut les utiliser.
Impossible par contre de vérifier avec la norme véritable, car je n'arrive pas à mettre la main sur un lien.
Marsh Posté le 05-09-2007 à 10:38:07
truc très chiant d'ailleurs de ne pas pouvoir mettre d'alias dans le group by, du coup je remets souvent mon bloc dans un from ou je select et groupe au dessous ou alors c'est copier des case a rallonge dans le select et dans le group by, et a maintenir c'est la mert, personne n'est ceo d'oracle ici pour leur en toucher un mot?
Marsh Posté le 05-09-2007 à 10:40:35
chuis pas ceo, mais je peux donner la raison : "c'est d'la merde"
Marsh Posté le 05-09-2007 à 12:59:53
MagicBuzz > sql 92 : http://www.contrib.andrew.cmu.edu/ [...] ql1992.txt
Je n'ai pas regardé le document en détails mais d'après l'entête c'est la version normé "ISO/CEI 9075:1992" (9075 pour la norme SQL, le 92 pour l'année de la normalisation).
Bonne lecture.
Marsh Posté le 05-09-2007 à 14:16:42
|
De ce que je comprends, donc...
- Ce sont des références aux "colonnes" du résultat de la requête. Par contre, ils parlent du résultat du FROM ou du WHERE, pas celui du SELECT. Hors c'est le SELECT qui amène les alias. Du coup, je me pose des questions : pas de fonctions, mais pas d'alias non plus. Ca me semble très biaisé, et on comprend pourquoi le SQL 1999 a été inventé si je comprends bien le truc.
- Ils ne disent pas explicitement que toutes les colonnes de la clause SELECT doivent se trouver dans la clause group by. Cependant, ils ne parlent pas non plus de fonctions d'agrégat. Et effectivement, un GROUP BY sans fonction d'aggrégat peut ne porter que sur un seul champ, ça marchera. En fait, je vais regarder du côté des fonctions d'aggrégat, je pense que c'est pas la définition de la clause GROUP BY qui contient la réponse
Marsh Posté le 05-09-2007 à 14:30:51
D'après l'exemple page 617, c'est bien les colonnes non issues du SELECT qui sont utilisée.
Ainsi, :
SELECT count(*)
FROM ...
WHERE ...
GROUP BY untrucpasdansleselect
Est valide.
Ceci implique donc que j'ai raison en indiquant que le GROUP BY ne peut pas contenir d'alias.
Par contre, on dirait bien que le GROUP BY ne peut pas contenir de calculs, ce qui me semble étrange.
Ca voudrait dire qu'il est implossible d'avoir un truc du genre :
select count(*), hour(timestamp)
from log
group by hour(timestamp)
mais à la place :
select count(*), timestamp
from log
group by timestamp
ce qui à coup sûr, ne peut pas donner le même résultat !
Par contre, j'ai rien trouvé d'autre comme info...
Pour MIN() etc. ils ne parlent même pas de la clause (pourtant obligatoire) group by...
Marsh Posté le 01-09-2007 à 22:22:53
Bonjour,
je me pose une question toute simple chaque fois que je dois faire une jointure. laquelle choisir ?
Est-ce qu'il vaut mieux privilégier une jointure dans le from via inner join ON, join on, left join On ou alors une jointure dans le where