Requête très simple, mais ? - SQL/NoSQL - Programmation
Marsh Posté le 19-09-2007 à 11:04:43
select nom_film , cat1.NOM_CAT, cat2.NOM_CAT
FROM FILM , CATEGORIE as cat1, CATEGORIE as cat2
WHERE FILM.ID_CAT1 = cat1.ID_CAT AND FILM.ID_CAT2 = cat2.ID_CAT
Marsh Posté le 19-09-2007 à 11:04:45
Quel est le problème ? Tu as 2 clés étrangères vers la même table, tu fais 2 jointures
edit: ah bah on te le file tout cuit
Marsh Posté le 19-09-2007 à 11:07:26
Merci pour le boulot tout cuit, mais rassures-toi pikti, j'ai cherché, mais n'étant pas spécialiste, je n'ai pas réussi.
Par contre, j'aurais pu le faire graphiquement sous access et regarder le résultat SQL, je n'y ai même pas mensé. Merci flo850 !
Marsh Posté le 19-09-2007 à 11:10:33
En fait, j'ignorais qu'on pouvait faire ça :
FROM CATEGORIE as cat1, CATEGORIE as cat2
Merci encore, ça marche impecc !
Marsh Posté le 19-09-2007 à 13:17:55
flo850 a écrit : select nom_film , cat1.NOM_CAT, cat2.NOM_CAT |
merci d'éviter les jointures par WHERE et d'utiliser la syntaxe normalisée JOIN stp
Marsh Posté le 19-09-2007 à 13:48:54
Tu veux dire que ça donnerait :
select nom_film , cat1.NOM_CAT, cat2.NOM_CAT
FROM FILM JOIN CATEGORIE as cat1, CATEGORIE as cat2
ON ((FILM.ID_CAT1 = cat1.ID_CAT) AND (FILM.ID_CAT2 = cat2.ID_CAT))
??
Marsh Posté le 19-09-2007 à 14:10:59
Harkonnen a écrit : |
DO NOT WANT
sur les requetes comme ca, ca alourdi la syntaxe inutilement
007seb a écrit : Tu veux dire que ça donnerait : |
plutot quelque chose du genre
SELECT nomf_film , cat1.NOM_CAT, cat2.NOM_CAT
FROM FILM
LEFT JOIN cat_film as cat1 ON FILM.ID_CAT1 = cat1.ID_CAT
LEFT JOIN cat_film as cat2 ON FILM.ID_CAT2 = cat2.ID_CAT
Marsh Posté le 19-09-2007 à 14:24:11
flo850 a écrit : |
I WANT §§§
les jointures WHERE :
- sont dépassées (syntaxe de 1986)
- ne facilitent pas la distinction des différentes clauses WHERE dans une requête
le WHERE sert à restreindre le résultat d'une requete, alors qu'une jointure réalise le contraire ("agrandit" la table), c'est un peu une hérésie d'utiliser un mot clé restrictif pour élargir une table
Marsh Posté le 19-09-2007 à 14:35:01
Bof. Moi je suis habitué aux deux syntaxes, et très franchement, tout dépend de la propreté du code surtout.
Notamment, ici je vois des "JOIN" tout court ou des "LEFT JOIN" tout court... Bah désolé, c'est pas du SQL.
En SQL, on a 6 types de jointures :
INNER JOIN
LEFT OUTER JOIN
RIGHT OUTER JOIN
FULL OUTER JOIN (Supporté par peu de SGBD, dommage, ça peut servir des fois...)
CROSS JOIN
NATURAL JOIN (Supporté par quasiement aucun SGBD, et je le déconseille très fort, c'est comme le "select *". Je ne suis même pas sûr qu'il soit dans la norme)
ET RIEN D'AUTRE. On met la syntaxe complète, pas des raccourcis qui portent à confusion.
Un "LEFT JOIN", si c'est un "LEFT INNER JOIN" c'est pas pareil qu'un "LEFT OUTER JOIN" (le INNER peut être droite ou gauche, peut importe. Sur les anciens SGBD, on pouvait indiquer dans quel sens faire la jointure, pour des raisons de performances, aujourd'hui ça n'est plus supporté et inutile).
Le coup du "JOIN" tout court... Super, ça veut rien dire... On sait absolument pas de quel type de jointure il s'agit.
Bref, quite à utiliser les jointures n'importe comment, autant utiliser la clause WHERE, ça aura au moins le mérite d'être sans équivoque à la lecture des critères.
Donc :
- seb007 : n'utilise pas JOIN tout seul, dit que c'est un INNER que tu veux...
- flo850 : arrête d'utiliser des LEFT JOIN (déjà, utilise la syntaxe LEFT OUTER JOIN) et utilise plutôt des INNER JOIN quand t'as pas besoin de la fonctionnalité OUTER... Là tu mets à genoux ton SGBD pour rien
Marsh Posté le 19-09-2007 à 14:49:44
Harkonnen a écrit : |
1er argument pourri
Harkonnen a écrit : |
je te réécrit ce que je t'ai dit avant, pour les petites requetes ca alourdit plus qu'autre chose
Harkonnen a écrit : |
c'est un peu de la branlette comme argument
Marsh Posté le 19-09-2007 à 15:07:24
Je vais quand même abonder un peu dans le sens d'Harko, notamment sur son troisième argument.
Outre l'aspect sémentique, c'est aussi (et surtout) ce que fait le moteur de la base de données. Ainsi, une jointure explicite sera généralement plus performante qu'une liste de tables dans le FROM, suivient d'une série de filtres dans le WHERE.
Non pas que le SGBD soit stupide, et fasse un CROSS JOIN de toutes les tables avant de les filtrers (quand même pas), mais simplement que lorsqu'il va tenter de traduire la syntaxe sans jointures explicites, il va souvent perdre ses petits, mettre la charrue avant les boeufs, et se retrouver à faire des jointures bien plus grosses que prévues.
Par exemple (totalement abstrait) :
Table TIE : 100 lignes
Table EVE : 1 000 lignes
Table EVP : 10 000 lignes
select *
from tie, eve, evp
where evp.eve_id = eve.id
and eve.tie_id = tie.id
and tie.nom = 'magicbuzz'
and eve.codeta = 'V'
=> Le SGBD peut se lancer dans une jointure entre eve et evp, et ainsi parcourir 10 000 lignes 1000 fois de suite, s'appercevoir qu'il faut virer toutes les lignes où codeta <> 'V', avant de faire la jointure avec TIE, pour finalement se rendre compte qu'on ne veut à priori qu'une ou deux lignes de TIE, ce qui rends inutile 90% des traîtements effectués lors de la jointure entre EVE et EVP.
Alors que :
select *
from tie
inner join eve on eve.tie_id = tie.id
inner join evp on evp.eve_id = eve.id
where tie.nom = 'magicbuzz'
and eve.codeta = 'V'
=> Le SGBD cherche les lignes de TIE qui correspondent à la clause where, donc que les id correspondant 'magicbuzz'.
=> Ensuite, il lie les lignes retournées à la table EVE, puis filtre sur le codeta
=> Et enfin, il lie les lignes retournées à la EVP.
Cette dernière étape est dont très rapide, alors qu'elle était très lente au départ.
CEPENDANT !
Il faut faire attention, car avec des jointures explicites on peut aussi perdre le SGBD :
select *
from evp
inner join eve on eve.id = evp.eve_id
inner join tie on tie.id = eve.tie_id
where tie.nom = 'magicbuzz'
and eve.codeta = 'V'
=> Ceci risque de "forcer" le SGBD à coller la charrue avant les boeufs !
Bref, l'un ou l'autre, c'est pas toujours évident. Il faut surtout savoir ce qu'on fait
Marsh Posté le 19-09-2007 à 15:13:03
flo850 a écrit :
|
je vois pas pourquoi, JOIN (et toutes ses variantes) sont normalisés, donc autant les utiliser.
flo850 a écrit :
|
pas d'accord, ça améliore la lisibilité. sur une requête avec une jointure WHERE, on ne distingue pas au 1er coup d'œil si la requête est filtrée ou comporte uniquement une jointure. et pour peu que les champs des tables jointes comportent des noms "exotiques" et que la requete soit longue, ça peut tourner au cauchemar pour identifier une jointure au 1er coup d'oeil.
exemple (vécu) :
Code :
|
la requete faisait une dizaine de lignes, avec une palanquée de WHERE. les noms des champs "in_name" et "customerleft" sont des clés primaires et étrangeres (pas de "ID" dans ces noms de champs, pratique pour distinguer une éventuelle jointure ). avec un INNER JOIN, j'aurais vu de suite que :
- la requete comportait une jointure
- les champs "in_name" et "customerleft" étaient des clés primaires et étrangères.
et pour peu que la requete comporte plusieurs jointures, je te raconte pas le bordel
flo850 a écrit :
|
c'est une question de sémantique
un autre argument ? sur la requete suscitée, j'ai voulu, à des fins de test, supprimer tous les WHERE (ceci avant que je m'aperçoive qu'elle comportait des jointures). résultat : j'ai eu droit à un joli produit en croix qui m'a explosé le serveur et m'a attiré les foudres du client
bref ! que la requete fasse 1/2 ligne ou 10 pages, il faut absolument dégager les jointures WHERE
MagicBuzz a écrit :
|
si si, ça arrive, je t'assure
Marsh Posté le 19-09-2007 à 15:37:32
Si j'avais su que ça déclencherait autant d'énervements, j'aurais cherché un peu plus par moi même dans la doc (mais là, c'est un petit dév pour le boulot, et plus c'est vite fait, plus ça m'arrange :-))
En tous cas, merci à tous, j'ai appris quelque chose. Pour ceux que ça intéresse, ma requête est écrite comme cela (les film et catégories n'étaient qu'un prétexte/exemple) :
SELECT DISTINCT S.ID_SALON, S.T_NOM, S.T_DESC_FR, S.D_DATE_DEBUT, S.D_DATE_FIN AS DATE_FIN, V.T_VILLE, C1.FR AS CAT1, C2.FR AS CAT2 FROM T_SALON AS S INNER JOIN T_CATEGORIE AS C1 ON (S.ID_CATEGORIE=C1.ID_CATEGORIE) INNER JOIN T_CATEGORIE AS C2 ON (S.ID_CATEGORIE2=C2.ID_CATEGORIE) INNER JOIN T_VILLE AS V ON (V.ID_VILLE=S.ID_VILLE)"
Normalement, c'est bon... d'après ce que vous avez pu me dire !
Marsh Posté le 19-09-2007 à 15:43:36
en regardant vite fait, ta requête à l'air bonne en effet.
bon, j'ai pas creusé non plus
Marsh Posté le 19-09-2007 à 11:00:05
Bonjour,
J'ai une requête extrêmement simple à réaliser (pour vous ;-), mais je sèche...
Je simplifie :
J'ai 2 tables, une nommée FILM et une nommée CATEGORIE
la table catégorie serait comme ceci par exemple :
ID_CAT NOM_CAT
1 THRILLER
2 COMEDIE
3 THEATRE
4 DRAME
et la table FILM serait comme ceci :
ID_FILM NOM_FILM ID_CAT1 ID_CAT2
1 E.T. 1 2
2 A.I. 1 4
3 BAMBY 2 4
Je voudrais une requête qui me retourne un résultat du type (sachant que FILM.ID_CAT1 et FILM.ID_CAT2 sont liés à CATEGORIE.ID_CAT vous l'aurez compris) :
E.T. THRILLER COMEDIE
A.I. THRILLER DRAME
BAMBY COMEDIE DRAME
et je n'y arrive pas :-)
Merci à vous.