Requête très simple, mais ?

Requête très simple, mais ? - SQL/NoSQL - Programmation

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.

Reply

Marsh Posté le 19-09-2007 à 11:00:05   

Reply

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

Message cité 1 fois
Message édité par flo850 le 19-09-2007 à 11:05:27
Reply

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 :)


Message édité par pikti le 19-09-2007 à 11:05:08
Reply

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 !

Reply

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 !

Reply

Marsh Posté le 19-09-2007 à 13:17:55    

flo850 a écrit :

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


merci d'éviter les jointures par WHERE et d'utiliser la syntaxe normalisée JOIN stp :o

Reply

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))
 
??
 

Reply

Marsh Posté le 19-09-2007 à 14:10:59    

Harkonnen a écrit :


merci d'éviter les jointures par WHERE et d'utiliser la syntaxe normalisée JOIN stp :o


DO NOT WANT   [:banguy]  
sur les requetes comme ca, ca alourdi la syntaxe inutilement

007seb a écrit :

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))
 
??
 


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

Reply

Marsh Posté le 19-09-2007 à 14:24:11    

flo850 a écrit :


DO NOT WANT   [:banguy]  


I WANT §§§ :fou:
 
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 [:el g]

Reply

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 :p


Message édité par MagicBuzz le 19-09-2007 à 14:36:04
Reply

Marsh Posté le 19-09-2007 à 14:35:01   

Reply

Marsh Posté le 19-09-2007 à 14:49:44    

Harkonnen a écrit :


I WANT §§§ :fou:
 
les jointures WHERE :
- sont dépassées (syntaxe de 1986)


1er argument pourri

Harkonnen a écrit :


- ne facilitent pas la distinction des différentes clauses WHERE dans une requête


je te réécrit ce que je t'ai dit avant, pour les petites requetes ca alourdit plus qu'autre chose  

Harkonnen a écrit :


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 [:el g]


c'est un peu de la branlette comme argument

Reply

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 ;)

Reply

Marsh Posté le 19-09-2007 à 15:13:03    

flo850 a écrit :


1er argument pourri


je vois pas pourquoi, JOIN (et toutes ses variantes) sont normalisés, donc autant les utiliser.

 
flo850 a écrit :


je te réécrit ce que je t'ai dit avant, pour les petites requetes ca alourdit plus qu'autre chose


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 :
  1. SELECT machin, bidule, chose, kaka FROM table1, table2 WHERE table1.in_name = table2.customerleft


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 [:bien]). 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 [:el g]

 


flo850 a écrit :


c'est un peu de la branlette comme argument


c'est une question de sémantique :spamafote:
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 [:el g]

 

bref ! que la requete fasse 1/2 ligne ou 10 pages, il faut absolument dégager les jointures WHERE :o

 
MagicBuzz a écrit :


Non pas que le SGBD soit stupide, et fasse un CROSS JOIN de toutes les tables avant de les filtrers (quand même pas),


si si, ça arrive, je t'assure [:el g]


Message édité par Harkonnen le 19-09-2007 à 15:14:37
Reply

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 !

Reply

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 ;)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed