Différence entre deux Requêtes - SQL/NoSQL - Programmation
Marsh Posté le 30-12-2009 à 23:55:59
oh putain
si tu veux éviter les WHERE à la con, renseigne toi sur les jointures via le mot clé JOIN, et recherche mes interventions sur la cat SQL qui fustigent les jointures par WHERE
Marsh Posté le 31-12-2009 à 09:16:26
Cf le lien de ma signature ( )
Marsh Posté le 31-12-2009 à 10:03:50
The Murderer a écrit : SELECT id_produit FROM produit WHERE id_produit IN (SELECT id_produit FROM produit WHERE description_produit = 'pain') ; |
Tu te rends compte que ta requête revient à
Code :
|
The Murderer a écrit : ça me permettrais d'éviter de mettre deux WHERE à la suite ce qui n'est pas possible il me semble. |
Peux-tu developper ?
Marsh Posté le 31-12-2009 à 10:16:04
Harkonnen a écrit : oh putain |
+1
Where c'est pour les restrictions, join pour les jointures.
La bonne requete (la premiere) est donc :
Code :
|
La deuxieme est a eviter, les perfs du 'in' equivallent au or sont degeulasses en general et peuvent ne pas utiliser d'index. Si tu tiens quand meme a l'utiliser, mets au moins un distinct dans le sous select ou plutot prefere utiliser un clause 'exists' souvent moins penalisante :
Code :
|
mais c'est nettement moins performant qu'une jointure.
Quand a la derniere, anapajari a tout dit, il est souvent plus simple d'enrichir la clause where que de faire des auto-sous-jointures a la mord moi le noeud.
Marsh Posté le 31-12-2009 à 10:18:52
Pour la diff entre IN et EXISTS, je tenais le même discourt.
Finalement, après différents tests (cf. ma signature) j'ai du admettre que Oracle et Microsoft tout du moins, on particulièrement beaucoup travaillés sur le IN, qui est étonnamment souvent plus rapide que le EXISTS (moi aussi ça m'a laissé sur le derrière)
Marsh Posté le 31-12-2009 à 11:25:42
Oui, c'est en partie vrai car les in sont automatiquement transformes en 'union' depuis un certain temps par ces deux systemes.
Par contre, si tu lis bien le sujet, c'est du mysql et mysql est une vraie merde de ce cote.
Compare une requete avec des or et une union (meme perfs oracle et sqlserveur a peu de chose pres) aux variantes mysql et pleure si tu utilise ce dernier.
==> Edit grammaire et orthographe trop pitoyables pour rester en l'etat meme si ce n'est pas encore parfait.
Marsh Posté le 31-12-2009 à 11:55:20
fred777888999 a écrit : les perfs du 'in' equivallent au or sont degeulasses en general et peuvent ne pas utiliser d'index. |
fred777888999 a écrit : Oui, c'est en partie vrai car les in sont automatiquement transformes en 'union' depuis un certain temps par ces deux systemes. |
Source ou explication pour ces deux points, ça m'interesse
Marsh Posté le 31-12-2009 à 13:48:03
anapajari a écrit :
|
anapajari a écrit : |
Merci pour vos réponses !!
En fait, j'ai une requête assez complexe à ecrire et je suis un peu perdu.
J'aimerais joindre plusieurs tables :
-Table rubrique --> id_rubrique//nom_rubrique
-Table rubrique_sup --> id_rubrique//id_rub_sup
-Table rubriques_produits --> id_rubrique//id_produit
-Table produit --> id_produit//libelle_produit//prix_produit
J'aimerais connaitre le nom des rubriques (nom_rubrique) ayant pour rubrique supérieure 2 (id_rub_sup = '2') et contenant tout les produits répondants a un certain mot clé.
J'ai essayé de l'ecrire comme ceci :
SELECT * FROM rubrique R JOIN rubrique_sup RS ON R.id_rubrique = RS.id_rubrique
WHERE RS.id_rub_sup = '.$idsup.' AND R.id_rubrique IN (SELECT RP.id_rubrique FROM rubriques_produit RP JOIN rubrique R ON RP.id_rubrique = R.id_rubrique WHERE RP.id_rubrique
IN (SELECT DISTINCT id_rubrique FROM rubriques_produit WHERE id_produit
IN (SELECT DISTINCT id_produit MATCH (libelle_produit) AGAINST ('.$rech.')
FROM produit WHERE MATCH (libelle_produit) AGAINST ('.$rech.'))))' ;
Je ne sais pas quand utiliser des IN et quand utiliser des JOIN sachant que cela se ressemble j'ai l'impression.
De plus je veux la jointure des rubriques ayant telle rub_sup et des rubriques ayant tels produits et je ne pense pas ici que le AND soit le bon mot.
Merci pour votre aide.
Marsh Posté le 31-12-2009 à 14:09:02
Ben c'est que des jointures que je vois dans ton truc, la requete est elementaire...
Code :
|
ou alors qq chose de simple m'as echape mais je ne vois pas quoi ?
Marsh Posté le 31-12-2009 à 14:09:43
Tu peux ajouter un distinct pour eviter d'avoir les rubriques en doublons, ce sera plus propre...
Marsh Posté le 31-12-2009 à 14:14:47
Code :
|
A noter que je ne suis pas sûr de la syntaxe du MATCH() AGAINST() que je n'utilise pas (je travaille jamais sur MySQL)
En tout cas, à ce détail près, t'as rien de plus compliqué que ça dans ta requête...
Grrrr, grillé par fred
Marsh Posté le 31-12-2009 à 14:18:47
==> surtout tu as oublie le group_by pour ta fonction de comptage, on va mettre ca sur le compte du nouvel an
Marsh Posté le 31-12-2009 à 14:38:21
anapajari a écrit : |
Si tu as mysql, oracle et/ou sql-serveur, le test est tres facile a faire...
Code :
|
Utilise l'index
Code :
|
l'utilise aussi
Code :
|
ou
Code :
|
fait un magnifique full scan en mysql, mais utilise bien l'index en oracle ou sqlserveur. J'en suis tombe sur le cul quand une des pages d'un de nos sites rammait a mort suite a la modif d'un collegue qui avait rajoute un or sur un colonne de clef primaire.
Ce truc est Ok en oracle depuis la version 8 au moins
Je n'ai pas verifie si c'etait vrai avec tous les moteurs mysql ou seulement celui qu'on utilisait (je ne sais plus lequel c'etait).
Marsh Posté le 31-12-2009 à 14:38:37
fred777888999> c'est possible mon explication ou pas ? (cf mon post plus haut), merci
Marsh Posté le 31-12-2009 à 14:56:16
fred777888999 a écrit : ==> surtout tu as oublie le group_by pour ta fonction de comptage, on va mettre ca sur le compte du nouvel an |
Et sur le fait que ça doit faire 6 mois que j'ai pas écrit une seule requête
Marsh Posté le 31-12-2009 à 15:27:25
fred777888999 a écrit :
|
C'est pas le cas sur une 5.0.37
EXPLAIN EXTENDED select * from maTable where monChamps=1 or monChamps=2; EXPLAIN EXTENDED select * from maTable where monChamps in (1,2); EXPLAIN EXTENDED select * from maTable where monChamps=1 union select * from maTable where monChamps = 2; |
Par ailleurs sur le point oracle (conversion in => union), j'ai trouvé ça qui montrerait plutot que l'optimizer transforme les in/exists en join (et pas en union)...
Marsh Posté le 31-12-2009 à 15:41:14
Effectivement, ton or est correctement fait, mais je peux t'assurer que ce n'etait pas le cas sur l'optimisation qu'on a du faire J'en ai donc tire abusivement la conclusion que mysql ne faisait JAMAIS l'optimisation alors que ce n'est visiblement pas le cas.
Merci de cette precision
Pour le second point, oui, bien sur, il faut bien faire une jointure sous la sous-requete avant de faire l'union ensuite pour ramener les deux lignes du exists. Mais je t'accorde volontier que le terme 'transforme en union' est un abus de language juste pour rendre l'idee comprehensible.
Marsh Posté le 30-12-2009 à 23:01:00
Bonjour à tous,
J'aimerais savoir la différence entre ces deux requête mysql :
- SELECT * FROM produit P, rubrique R WHERE P.id_produit = R.id_produit AND R.id_rubrique = 'legumes' ;
- SELECT * FROM produit WHERE id_produit IN (SELECT id_produit FROM rubrique WHERE id_rubrique = 'legumes') ;
Peut-on également faire une sous-requête sur une même table ?
- SELECT id_produit FROM produit WHERE id_produit IN (SELECT id_produit FROM produit WHERE description_produit = 'pain') ;
Cela paraît ridicule mais ça me permettrais d'éviter de mettre deux WHERE à la suite ce qui n'est pas possible il me semble.
Merci pour vos réponses.