Page 1 sur 2
Mysql : problème plusieurs requêtes avec "ou"
Posté : 09 mai 2005, 09:39
par quick25
Bonjour à tous,
voila je vous présente mon problème :
Je bosse sur une application qui gère des questions de mathématiques dans une base donnée, avec une interface PHP. Et il existe une fonction "recherche" qui permet de rechercher les questions désirées. Et il est possible de faire plusieurs requêtes de recherche de suite, et c'est là que se situe mon problème car quand entre 2 requetes on met un "ou" ca ne marche pas, en effet ca cherche pendant un moment et ca plante, et pour l'avoir tester sous mysql (sans php) ca envoie des milliers de requetes.
Code : Tout sélectionner
select distinct Q.cleQuestion from QUESTION Q where Q.cleQuestion='100' or Q.cleQuestion IN (select distinct Q.cleQuestion from QUESTION Q where Q.cleQuestion='101')
Je pense que le problème vient du fait qu'il y a 2 select et qu'avec le "ou" ca recherche partout, et ca fait planter l'application.(elle utilise des sessions).
J'espere que vous aurez compris mon problème et que qqcn pourra m'apporter des réponses si possible. Merci beaucoup d'avance...
Posté : 09 mai 2005, 10:08
par Ripat
Pourquoi pas simplement :
Code : Tout sélectionner
SELECT DISTINCT Q.cleQuestion
FROM QUESTION Q
WHERE Q.cleQuestion='100' OR Q.cleQuestion ='101'
Posté : 09 mai 2005, 10:23
par albat
On peut encore simplifier l'écriture (déjà bien nettoyée par
Ripat),
SELECT DISTINCT Q.cleQuestion
FROM question Q
WHERE Q.cleQuestion = 100
OR Q.cleQuestion = 101
mais là, je me pose une question :
À quoi peut bien servir cette requête ???

Posté : 09 mai 2005, 14:20
par Murphy
Bein tout simplement à afficher deux questions dont la clé serait 100 ou 101 .
Mais là il ya un autre problème d'après cette solution...
Comment gérer les priorités si l'on veut faire par exemple:
select distinct Q.cleQuestion
from QUESTION Q,SENS S
where Q.cleQuestion='100'
or S.cleSens='10'
and Q.cleQuestion='100'
Bizzarement ça fait planter Mysql selon les requêtes que l'ont fait avec le ou logique ...

oups
Posté : 09 mai 2005, 14:22
par Murphy
=> avec une cleQuestion égal à 101
Posté : 09 mai 2005, 14:41
par Ripat
Attention à la précédence des opérateurs logiques!
Si tu écris
Code : Tout sélectionner
SELECT DISTINCT Q.cleQuestion
FROM question Q, sens S
WHERE Q.cleQuestion='100'
OR S.cleSens='10'
AND Q.cleQuestion='101'
Revient à dire:
Code : Tout sélectionner
SELECT DISTINCT Q.cleQuestion
FROM question Q, sens S
WHERE Q.cleQuestion='100'
OR (S.cleSens='10' AND Q.cleQuestion='101')
Cela correspond t'il à ce que tu veux faire?
Lecture:
http://dev.mysql.com/doc/mysql/fr/opera ... dence.html
Edit Hum, je me suis un peu emmêllé les pinceaux sur ce coup là...
Posté : 09 mai 2005, 15:07
par Murphy
Merci c'est un détail que je n'avais pas pris en compte
Voilà une requete mieux apropriée :
select distinct Q.cleQuestion from QUESTION Q,SENS S,ORIGINE O,FACILITE FA where S.cleSens='1' or Q.cleQuestion='1011' and O.cleOrigine='4' and FA.numFacilite='60' and Q.cleSens=S.cleSens and Q.cleOrigine=O.cleOrigine and Q.numFacilite =FA.numFacilite
En faite ma réelle question est :
Est-ce que le OU imbrique tout le reste de la sélection ( ce qu'il y a après ):
Q.cleQuestion='1011' and O.cleOrigine='4' and FA.numFacilite='60'
Posté : 09 mai 2005, 15:19
par Murphy
ok j'ai compris lol
Posté : 09 mai 2005, 15:21
par quick25
Attention à la précédence des opérateurs logiques!
Si tu écris
Code : Tout sélectionner
SELECT DISTINCT Q.cleQuestion
FROM question Q, sens S
WHERE Q.cleQuestion='100'
OR S.cleSens='10'
AND Q.cleQuestion='101'
Revient à dire:
Code : Tout sélectionner
SELECT DISTINCT Q.cleQuestion
FROM question Q, sens S
WHERE Q.cleQuestion='100'
OR (S.cleSens='10' AND Q.cleQuestion='101')
mon collègue (Murphy) et moi somme entrain de tester cette solution, mais c est vrai que les règles de priorité nous ont un peu échappé

!
En espérant que ca va mieux aller, mais déja merci bcp d'avance pour les réponses déja postées.
Posté : 09 mai 2005, 15:54
par albat
Bein tout simplement à afficher deux questions dont la clé serait 100 ou 101 .
Tu en es bien sûr ?...
Alors, vérifie ta requête car telle que tu l'as écrite,
tout ce qu'elle va te retourner, c'est 100 et/ou 101.
Passionnant, non ?

Posté : 09 mai 2005, 16:03
par Murphy
Dans la sélection telle qu'elle vient d'être faite, on sélectionne la question 100 ou la question 101 ( pas dans le sens absolu du terme

) tandis que si on fait la sélection avec un 'et' on aura aucun résultat car une question ne peut avoir deux numéro ...
donc avec le 'ou' on obtient bien la question 100 et la 101 comme résultat
Nouvelle question
Posté : 09 mai 2005, 16:08
par Murphy
J'ai compris les priorités donc voilà un bon exemple en mettant les parentheses sans inclure les jointures.
select distinct Q.cleQuestion
from QUESTION Q,ORIGINE O,FACILITE FA
where Q.cleQuestion='321'
or ( O.cleOrigine='7' and FA.numFacilite='40' )
and Q.cleOrigine=O.cleOrigine
and Q.numFacilite =FA.numFacilite
Et en incluant les jointures dans les prenthèses
select distinct Q.cleQuestion
from QUESTION Q,ORIGINE O,FACILITE FA
where Q.cleQuestion='321'
or ( O.cleOrigine='7' and FA.numFacilite='40'
and Q.cleOrigine=O.cleOrigine
and Q.numFacilite =FA.numFacilite)
Qu'est-ce qui est conseillé ?
Posté : 09 mai 2005, 16:28
par Ripat
Tout d'abord de séparer jointure et conditions. Ce sont deux choses différentes. Lis ceci:
UN CONSEIL IMPORTANT
Dans la mesure du possible, utilisez toujours un opérateur de jointure normalisé Sql2 (mot clef JOIN).
En effet :
* Les jointures faites dans la clause WHERE (ancienne syntaxe de 1986 !) ne permettent pas de faire la distinction de prime abord entre ce qui relève du filtrage et ce qui relève de la jointure.
* Il est à priori absurde de vouloir filtrer dans le WHERE (ce qui restreint les données du résultat) et de voiloir "élargir" ce résultat par une jointure dans la même clause WHERE de filtrage.
* La lisibilité des requêtes est plus grande en utilisant la syntaxe à base de JOIN, en isolant ce qui est du filtrage et de la jointure, mais aussi en isolant avec clarté chaque condition de jointures entre chaque couples de table.
* L'optimisation d'exécution de la requête est souvent plus pointue du fait de l'utilisation du JOIN.
* Lorsque l'on utilise l'ancienne syntaxe et que l'on supprime la clause WHERE a des fins de tests, le moteur SQL réalise le produit cartésiens des tables ce qui revient la plupart du temps à mettre à genoux le serveur !
Ensuite tu peux t'occuper, tranquillement, des conditions. Si tu ne veux pas te casser la tête avec la précédences des opérateurs, mets des parenthèses, elle ne ralentissent pas l'exécution de la requête et elle permettent une bien meilleure lisibilité. Les parenthèses ont la plus haute priorité.
Edit: exemple
Code : Tout sélectionner
SELECT DISTINCT q.cleQuestion
FROM question q
JOIN origine o ON q.cleOrigine = o.cleOrigine
JOIN facilite fa ON q.numFacilite = fa.numFacilite
WHERE q.cleQuestion='321'
OR ( o.cleOrigine = '7' AND fa.numFacilite = '40')
Posté : 09 mai 2005, 16:52
par Murphy
Ok ça m'a l'air plus simple à réaliser avec ppur la contruction de la requete en php avec plusieurs variables servant à recuperer des parties de la requete ... => trop compliqué à expliqué ...
Bon je m'occupe de ça demain j'ai fini pour aujourd'hui !
Posté : 10 mai 2005, 08:33
par quick25
Bonjour à tous, nous revoilà
Une nouvelle petite question se pose :
Ripat pour ta proposition comment pourrions nous faire pour que dans une meme requête il soit possible de rechercher avec "et" (and), "ou"(or) et "sauf"?? La question c'est comment matérialiser ce "sauf". Merci bcp d'avance
