Précédent   Forum des professionnels en informatique > Bases de données > MySQL
MySQL Forum d'entraide MySQL. Avant de poster -> FAQ MySQL, Tutoriels MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/01/2012, 16h43   #1
Invité de passage
 
Inscription : décembre 2007
Messages : 18
Détails du profil
Informations forums :
Inscription : décembre 2007
Messages : 18
Points : 4
Points : 4
Par défaut requete msyql multiple

Bonjour à tous,

j'ai une requete qui est :
Code :
1
2
 
SELECT * FROM feuille1 WHERE activite1,activite2,activite3,activite4,activite5=1 OR activite1,activite2,activite3,activite4,activite5 =2
celle ci ne fonctionne pas, mais j'aimerai savoir comment je peux optimiser ce genre de requete qui sinon serait :
Code :
1
2
 
SELECT * FROM feuille1 WHERE activite1=1 OR activite2=1 OR activite3=1 OR activite4=1 OR activite5=1 OR  activite1=2 OR activite2=2 OR activite3=2 OR activite4=2OR activite5=2
merci
murdok74 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2012, 16h53   #2
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 654
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 654
Points : 2 656
Points : 2 656
Bonjour,

Vous ne pouvez pas l'optimiser.

Le problème ici est votre modélisation qui est inadaptée.

donc à partir de là... vous êtes obliger de faire des requêtes tordues pour répondre à votre besoin.


Donc si vous changez un peu votre modélisation :
Feuille-0,n----POSSEDE----1,1-Activité

Avec entre autre :
Feuille(feu_id, ...)
Activite(act_id,#feu_id, act_valeur, act_ordre)


On arrive à une requête plus simple :
Code :
1
2
3
4
5
 
SELECT *
FROM feuille feu
WHERE EXISTS (SELECT 1 FROM activite act WHERE act.feu_id = feu.feu_id AND 
act.act_valeur IN (1, 2) AND act.act_ordre IN (1, 2, 3, 4, 5))
Cinéphil me corrigera peut-être sur la partie modélisation.
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 10h03   #3
Membre émérite
 
Avatar de mactwist69
 
Homme Adrien
Développeur .NET
Inscription : janvier 2007
Messages : 924
Détails du profil
Informations personnelles :
Nom : Homme Adrien
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Industrie

Informations forums :
Inscription : janvier 2007
Messages : 924
Points : 978
Points : 978
La modélisation se tient. Par contre pour la requête il y a mieux que une requete imbriquer.

Un truc du genre irait beaucoup plus vite:

Code :
1
2
3
SELECT * FROM feuille
INNER JOIN Activite act ON feuille.id_feuille=act.feuille_id 
AND act.act_valeur IN (1, 2) AND act.act_ordre IN (1, 2, 3, 4, 5));
ou bien:

Code :
1
2
3
SELECT * FROM feuille
INNER JOIN Activite act ON feuille.id_feuille=act.feuille_id 
HAVING act.act_valeur IN (1, 2) AND act.act_ordre IN (1, 2, 3, 4, 5));
__________________
L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)
mactwist69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 10h40   #4
Membre régulier
 
Inscription : décembre 2006
Messages : 166
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 166
Points : 83
Points : 83
Envoyer un message via MSN à omdafer Envoyer un message via Skype™ à omdafer
Bonjour,
En fait punkoff et mactwist69 te conseilles d'avoir deux tables.
La table feuille1
Et une autre table activite avec l'id de feuille1, numéro d'activité(1,2,3,4,5...) et la valeur que tu recherches. ...Qui pourrait étendre le nombre d'activité possible ...activite6, .... au cas ou.


Sinon essais un truc du genre:
Code :
SELECT * FROM feuille1 WHERE activite_=1 OR activite_=2
omdafer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 11h20   #5
Membre émérite
 
Avatar de mactwist69
 
Homme Adrien
Développeur .NET
Inscription : janvier 2007
Messages : 924
Détails du profil
Informations personnelles :
Nom : Homme Adrien
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Industrie

Informations forums :
Inscription : janvier 2007
Messages : 924
Points : 978
Points : 978
Citation:
Envoyé par omdafer Voir le message
Bonjour,
En fait punkoff et mactwist69 te conseilles d'avoir deux tables.
La table feuille1
Et une autre table activite avec l'id de feuille1, numéro d'activité(1,2,3,4,5...) et la valeur que tu recherches. ...Qui pourrait étendre le nombre d'activité possible ...activite6, .... au cas ou.


Sinon essais un truc du genre:
Code :
SELECT * FROM feuille1 WHERE activite_=1 OR activite_=2
Oui mais ce que tu n'as pas vu c'est qu'il y a 5 activité par feuille qui chacun peuvent prendre 1 ou 2 ou autre choses...
__________________
L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)
mactwist69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 11h33   #6
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 654
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 654
Points : 2 656
Points : 2 656
Citation:
Envoyé par mactwist69 Voir le message
La modélisation se tient. Par contre pour la requête il y a mieux que une requete imbriquer.

Un truc du genre irait beaucoup plus vite:

Code :
1
2
3
SELECT * FROM feuille
INNER JOIN Activite act ON feuille.id_feuille=act.feuille_id 
AND act.act_valeur IN (1, 2) AND act.act_ordre IN (1, 2, 3, 4, 5));
Le résultat n'est pas le même.

Mise à part ça qu'est-ce qui motive le "mieux" dans votre argumentation ? (curiosité personnelle envers les mechanismes de MySql)


Citation:
ou bien:

Code :
1
2
3
SELECT * FROM feuille
INNER JOIN Activite act ON feuille.id_feuille=act.feuille_id 
HAVING act.act_valeur IN (1, 2) AND act.act_ordre IN (1, 2, 3, 4, 5));
Désolé mais ca c'est horrible niveau normalisation SQL, donc à moins d'un résultat beaucoup plus performant qu'une jointure normale je ne vois pas l'interet de le proposer.(ou alors en mettant un gros warning : truc horrible a ne jamais faire ! )
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 12h05   #7
Membre émérite
 
Avatar de mactwist69
 
Homme Adrien
Développeur .NET
Inscription : janvier 2007
Messages : 924
Détails du profil
Informations personnelles :
Nom : Homme Adrien
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Industrie

Informations forums :
Inscription : janvier 2007
Messages : 924
Points : 978
Points : 978
Cette réponse était basé sur le principe qu'il y a une nouvelle modélisation a deux table.

Je disai que ça:

Code :
1
2
3
SELECT * FROM feuille
INNER JOIN Activite act ON feuille.id_feuille=act.feuille_id 
AND act.act_valeur IN (1, 2) AND act.act_ordre IN (1, 2, 3, 4, 5));

C'est mieux que ça:

Code :
1
2
3
4
SELECT *
FROM feuille feu
WHERE EXISTS (SELECT 1 FROM activite act WHERE act.feu_id = feu.feu_id AND 
act.act_valeur IN (1, 2) AND act.act_ordre IN (1, 2, 3, 4, 5))
Tout simplement parce que dans le deuxième cas. MySQL va faire le premier select et pour chaque ligne va réeffectuer chaque sous requete. Donc il n'y a qu'a multiplié les deux tables pour cionnaitre le nombre de requete qu'il va faire.

Passé par un INNER JOIN, donc en utilisant les index des clé primaires, pour faire le lien il ne va utiliser que les index, tandis que la condition se fera sur qu'une seule des deux requetes au select (donc une seule fois).

J'ai proposer de mettre la condition dans le inner join (pour faire le where sur ce select), et j'ai proposer de la faire avec un Having, pour qu'il fasse la condition à la fin, sur le résultat, certe moins optimisé.
__________________
L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)
mactwist69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 12h11   #8
Membre régulier
 
Inscription : décembre 2006
Messages : 166
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 166
Points : 83
Points : 83
Envoyer un message via MSN à omdafer Envoyer un message via Skype™ à omdafer
Citation:
Envoyé par mactwist69 Voir le message
Oui mais ce que tu n'as pas vu c'est qu'il y a 5 activité par feuille qui chacun peuvent prendre 1 ou 2 ou autre choses...
Oui j'ai vu.

Ici l'idée c'est une table activite:
- 5 activité: numéro d'activité(1,2,3,4,5...) : act_ordre
- peuvent prendre 1 ou 2 ou autre choses: la valeur : act_valeur
- par feuille : l'id de la feuille qui fera liaison avec feuille : feu_id
Et biensûre l'id unique d'activité: act_id

Citation:
Envoyé par punkoff
Avec entre autre :
...
Activite(act_id,#feu_id, act_valeur, act_ordre)

Et la table feuille ou t’enlève les champ activité:
id de la feuille feu_id et le reste qui a dedans.
Citation:
Envoyé par punkoff
Avec entre autre :
Feuille(feu_id, ...)
omdafer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 12h15   #9
Membre émérite
 
Avatar de mactwist69
 
Homme Adrien
Développeur .NET
Inscription : janvier 2007
Messages : 924
Détails du profil
Informations personnelles :
Nom : Homme Adrien
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Industrie

Informations forums :
Inscription : janvier 2007
Messages : 924
Points : 978
Points : 978
Citation:
Envoyé par murdok74 Voir le message
Bonjour à tous,

j'ai une requete qui est :
Code :
1
2
 
SELECT * FROM feuille1 WHERE activite1,activite2,activite3,activite4,activite5=1 OR activite1,activite2,activite3,activite4,activite5 =2
celle ci ne fonctionne pas, mais j'aimerai savoir comment je peux optimiser ce genre de requete qui sinon serait :
Code :
1
2
 
SELECT * FROM feuille1 WHERE activite1=1 OR activite2=1 OR activite3=1 OR activite4=1 OR activite5=1 OR  activite1=2 OR activite2=2 OR activite3=2 OR activite4=2OR activite5=2
merci
En fait j'avais juste repris la requête proposer par punkoff. Mais en fait, j'aurai du mieux lire depuis le début, car la modélisation ne sert à rien.

Car feuille possède les 5 colonnes: Activité 1, 2, 3, 4, 5.

Tu voulais créer une table activité, pour factorisé. Mais ça sert à rien, y'a rien a factorisé. Car dans ce cas, au lieu de mettre Activité1=1, tu vas mettre Activité1= "l'id de l'activité 1", mais ça ne change pas que dans la table feuille, tu auras toujours 5 colonnes, pour mettre les 5 id de la table activité.

De plus, en modélisation, c'est facile a voir: un lien: 0.n -- 1.1, fait que tout ce qu'il y a dans 1.1, tu peux le mettre dans la table 0.n.

Donc... (c'est long je sais). Pour répondre à la question du début.

le seule moyen de factorisé ta requete:
Code :
WHERE activité1=1 OR Activité1=2
est de faire
Code :
WHERE Activité1 IN (1,2)
Y'a rien de plus a faire.
__________________
L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)
mactwist69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 12h16   #10
Membre régulier
 
Inscription : décembre 2006
Messages : 166
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 166
Points : 83
Points : 83
Envoyer un message via MSN à omdafer Envoyer un message via Skype™ à omdafer
Et en fait je te proposai avec le underscore (_) si tu gardais la structure de ta table.
Mais je sais plus si ça fonctionne avec des noms de champ. activiteX

Code :
SELECT * FROM feuille1 WHERE activite_ IN (1,2)
omdafer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 13h30   #11
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 654
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 654
Points : 2 656
Points : 2 656
Citation:
Envoyé par mactwist69 Voir le message
Tout simplement parce que dans le deuxième cas. MySQL va faire le premier select et pour chaque ligne va réeffectuer chaque sous requete. Donc il n'y a qu'a multiplié les deux tables pour cionnaitre le nombre de requete qu'il va faire.
Ah, pourtant : http://explainextended.com/2009/09/1...is-null-mysql/

Puis dans la doc MySql : http://dev.mysql.com/doc/refman/5.0/...ubqueries.html

etc

Aurai-je loupé quelque chose ?
Peut-être sur d'ancienne version de MySql est-ce le cas ?

Citation:
En fait j'avais juste repris la requête proposer par punkoff. Mais en fait, j'aurai du mieux lire depuis le début, car la modélisation ne sert à rien.

Car feuille possède les 5 colonnes: Activité 1, 2, 3, 4, 5.

Tu voulais créer une table activité, pour factorisé. Mais ça sert à rien, y'a rien a factorisé. Car dans ce cas, au lieu de mettre Activité1=1, tu vas mettre Activité1= "l'id de l'activité 1", mais ça ne change pas que dans la table feuille, tu auras toujours 5 colonnes, pour mettre les 5 id de la table activité.

De plus, en modélisation, c'est facile a voir: un lien: 0.n -- 1.1, fait que tout ce qu'il y a dans 1.1, tu peux le mettre dans la table 0.n.
Oui, vous avez raison dénormalisons par pure plaisir et ne regardons que le cas présent.

Maintenant si on y réfléchi à deux fois, changeons un peu les besoins :
- Retrouver les feuilles qui possèdent une ou plusieurs activités X
- Retrouver les feuilles qui ne possèdent pas d'activité.
- Retrouver les feuilles qui possèdent exactement l'activité X et Y
- Retrouver les feuilles qui possèdent au moins les activités X, Y et Z
- etc..

Tant de cas, simple au demeurant, qui deviennent vraiment complexe à traiter avec une telle structure initiale.

edit: tiens sinon je ne suis pas d'accord avec mon 1er poste !

Citation:
Donc si vous changez un peu votre modélisation :
Feuille-0,n----POSSEDE----1,1-Activité

Avec entre autre :
Feuille(feu_id, ...)
Activite(act_id,#feu_id, act_valeur, act_ordre)
En fait, la question que je me pose c'est savoir si ces "activités" font référence à une autre entité.

Si c'est le cas ...
Feuille-0,n----POSSEDE----0,n-Activité

Deviendra en fait :
Feuille(feu_id, ...)
Activite(act_id, act_nom, ....)
A_FEU_ACT(#feu_id, #act_id, fac_ordre, ...)


Bien, si ça n'est pas le cas, on reste sur :
Feuille-0,n----POSSEDE----1,1-Activité

Qui se modélise par :
Feuille(feu_id, ...)
Activite(act_id,#feu_id, act_valeur, act_ordre)
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 17/01/2012, 15h05   #12
Membre émérite
 
Avatar de mactwist69
 
Homme Adrien
Développeur .NET
Inscription : janvier 2007
Messages : 924
Détails du profil
Informations personnelles :
Nom : Homme Adrien
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Industrie

Informations forums :
Inscription : janvier 2007
Messages : 924
Points : 978
Points : 978
Pour la deuxième partie. Tu as raison. Ce qui m'avait échapper (je devrait lire plus ) c'est que le numéro d'activité était dans une colonne, et non plus dans un nom de colonne.
Mea Culpa donc.

Sur la première partie... j'ai fait des explains de requêtes équivalente. Voici le résultat synthétisé:

Avec exist
- Exists utilise un type eq_ref pour la sous requête (rapide)
- Mais cette requete n'est utile que si il n'y a pas de données à récupérer d'autre table que la première requete

EDIT
Avec jointure
- utilise un type ALL pour l'unique requete de jointure (pas de sous requete, mais passe sur toute les lignes des deux tables)
-> J'ai fait cette requete sur des tables MyIsam, donc forcement...
- possibilité de rapatrié des données des deux tables.

Donc dans notre cas, si tout ce qu'on veut est dans feuille, alors le exist est plus rapide.

Second mea culpa
__________________
L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)
mactwist69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 15h12   #13
Membre émérite
 
Avatar de mactwist69
 
Homme Adrien
Développeur .NET
Inscription : janvier 2007
Messages : 924
Détails du profil
Informations personnelles :
Nom : Homme Adrien
Localisation : France

Informations professionnelles :
Activité : Développeur .NET
Secteur : Industrie

Informations forums :
Inscription : janvier 2007
Messages : 924
Points : 978
Points : 978
Citation:
Envoyé par punkoff Voir le message
Ah, pourtant : http://explainextended.com/2009/09/1...is-null-mysql/

Si c'est le cas ...
Feuille-0,n----POSSEDE----0,n-Activité

Deviendra en fait :
Feuille(feu_id, ...)
Activite(act_id, act_nom, ....)
A_FEU_ACT(#feu_id, #act_id, fac_ordre, ...)
sur le schéma ok.

Par contre, fac_ordre (de A_FEU_ACT) devra aussi etre clé primaire, sinon il y aura un seul couple feuille/act possible, et non pas les n voulus.
__________________
L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)
mactwist69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 15h44   #14
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 654
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 654
Points : 2 656
Points : 2 656
hmm, non.

Les n le seront mais dans ce sens :
Code :
1
2
3
4
5
6
7
 
Activité
id      valeur
---------------
1       Sport
2       Cuisine
3       Lecture
On pourra affecté une activité à n différente feuille et une feuille pourra possédée n différentes activités (c'est ce qui est modélisé en fait).


Si on veut pouvoir affecter plusieurs fois une même activité selon un ordre donné alors la modélisation change :
Feuille-0,n--------POSSEDE--------0,n-Activite
Ordre-0,n-------------|

Par contre dans ce cas là la table "Ordre" n'est pas forcément nécessaire quand on passe au MPD ce qui peut effectivement entrainer une table d'association de ce type :
A_FEU_ACT(#feu_id, #act_id, fac_ordre)
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 19h49   #15
Membre régulier
 
Inscription : décembre 2006
Messages : 166
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 166
Points : 83
Points : 83
Envoyer un message via MSN à omdafer Envoyer un message via Skype™ à omdafer
En fait on débat mais on ne sait même pas si on a répondu à la question de murdok74. Il n'a pas encore répondu.
omdafer est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 19h09.


 
 
 
 
Partenaires

Hébergement Web