Forum Clubic

[MySQL] 2+1 requetes -> 1 requete ? [RESOLU...] - ...à moins d'1 meilleure idée ?

Edit : Changement du titre, suite a un nouveau problème

a moins qu’il y ait une limitation dans le nombre de AND ?


mysql> SELECT MM_PBSA_GB.Frame, MM_PBSA_GAS.Frame , MM_PBSA_GB.GB, MM_PBSA_GAS.Ele
    ->
    -> FROM MM_PBSA_GB, MM_PBSA_GAS, ParamPB, Molecule, Trajectory, prmtop
    ->
    -> WHERE MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
    ->
    -> AND MM_PBSA_GB.idParamGB = ParamGB.idParamGB
    -> AND MM_PBSA_GAS.idParamPhGas = ParamPhGas.idParamGas
    ->
    -> AND ParamGB.idMolecule = Molecule.idMolecule
    -> AND ParamGas.idMolecule = Molecule.idMolecule
    -> AND Molecule.Name = "whole"
    ->
    -> AND ParamGB.idTraj = Trajectory.idTraj
    -> AND ParamGas.idTraj =  Trajectory.idTraj
    -> AND Trajectory.Name = "nscm"
    ->
    -> AND ParamGB.idPrmtop = prmtop.idPrmtop
    -> AND prmtop.Name = "mbondi"
    ->
    -> AND ParamGB.idIgb = igb.idIgb
    -> AND igb.Name = "1"
    ->
    ->
    ->;
ERROR 1109: Unknown table 'ParamGB' in where clause
mysql> show tables;
+-------------------+
| Tables_in_MM_PBSA |
+-------------------+
| MM_PBSA_GAS       |
| MM_PBSA_GB        |
| MM_PBSA_PB        |
| MM_PBSA_SAS       |
| Molecule          |
| ParamGB           |
| ParamPB           |
| ParamPhGas        |
| ParamSAS          |
| Trajectory        |
| igb               |
| prmtop            |
+-------------------+
12 rows in set (0.00 sec)

mysql>

Donc on voit bien que la table ParamGB existe, mais il semble ne pas vouloir la voir…

Sinon, la requete est peut-etre fausse, c’etait un test, avant de vous demander conseil …

Je pige pas pourquoi dans ton FROM tu préfixes par le nom de ta base?
Démarre mysql avec --database? Ca t’évitera ce problème là.

Non, non, je ne prefixes pas par le nom de la base (à moins que je ne comprenne pas ce que tu veux dire) : la base s’appelle MM_PBSA, et les tables s’appellent MM_PBSA_GB, MM_PBSA_PB.

Sinon, tu veux dire genre :


$ mysql --database ma_base_de_donnees

?
Et imaginons que ca marche (ca me surprend, je vois rien qui indique ca dans le man, mais bref…), comment je fais pour faire tourner la requete sous PhpMyAdmin (ou j’obtiens la meme erreur…) ?

J’ai regardé rapidou, c’est pas just que ta base est pas dans ton “FROM” donc le “WHERE” le connaît pas.

La requête est fausse, remplace ton premier paramPB par paramGB, ou l’inverse… en fonction de ce que tu veux faire.
:sleep: faut se réveiller le matin!
:smiley:

Oh la la… le mauvais… Tout ca parceque j’ai voulu aller un peu vite…

Merci de ton attention

M’enfin tout ca pour arriver à : CA MARCHE PAS !!

Bon, je sai s pas si vous vous rappelez, vous m’avez deja fait une requete pour obtenir, à partir d’un nom de Molecule, d’un nom de trajectoire, et d’un nom de prmtop, tous les enregistrements correspondants dans la table PB.

Rappel : http://www.clubic.com/forum/index.php?showtopic=294888
et le schema correspondant : http://www.ibpc.fr/Perso/Nicolas.Guiot/img/DB_Complex_V4.png

Sauf que maintenant, je veux recupérer en meme temps les enregistrements de la table PhaseGas, pour ces memes noms de molecule, et de trajectoire (le parametre prmtop ne s’applique pas ici), pour a la fin additionner ensemble certaines valeurs, et obtenir ainsi les infos qui m’interessent.

J’ai voulu partir de la requete de l’autre fois, mais ca bugge (apres 10 min, la requete n’est toujours pas executée : j’imagine qu’elle doit etre mauvaise)

J’avais pense faire 2 fois la requete initiale : une fois pour la tabel Phasegas, une fois pour la table PB, mais ensuite, pour ajouter, faut refaire une nouvelle requete par-dessus pour egaler le numero de Frame, donc vraiment pas efficace.

Note : dans la requete que l’on voit au-dessus, les noms varient legerement par rapport au dessin : basez-vous plutot sur le dessin, ce sera probablement + facile pour vous, j’adapterai par la suite

Merci pour tout

A la limite, envoie la requête corrigée, peut-être qu’une bonne âme (moi :smiley: si j’a le temps) se pencheras dessus.
En attendant, comme je disais sur l’autre topic, une jointure sur beaucoup de tables ça peut prendre beaucoup de temps, essaye d’attendre plus de 10 minutes, tu sauras si c’est un problème de perf ou pas.
Les variations sur les perfs peuvent venir des index sur les tables, peut-être que cette nouvelle table n’est pas indexée sur ta clef de recherche.
Donc voir aussi tes index, mais moi je suis un bille en index, parcque c’est les admin qui s’occupent de tout ça, je connaît juste les principes, et les implications sur les perfs, les contraintes, …

Maintenant si tu peux découper tes requêtes: faire une poremière requête pour récupérer l’id comme dans ton précéent topic, puis avec cet id accéder à ta table.

edit: la jointure prend du temps quand ton produit cartésien conduit à multiplier les résultats avec des relation un poil complexes.

bon, j’ai pas tous compris ces histoires d’index, mais voici ce que donne ma requete qui plante (ou en tous cas met une plombe a s’executer, sur des tableaux de 1000 enregistremùents :

SELECT  MM_PBSA_GB.Frame, MM_PBSA_GAS.Frame , MM_PBSA_GB.GB, MM_PBSA_GAS.Ele

FROM  MM_PBSA_GB, MM_PBSA_GAS, ParamGB, Molecule, Trajectory, prmtop , igb, ParamPhGas

WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame

	AND MM_PBSA_GB.idParamGB = ParamGB.idParamGB
	AND MM_PBSA_GAS.idParamPhGas = ParamPhGas.idParamPhGas
	
	AND ParamGB.idMolecule = Molecule.idMolecule
	AND ParamPhGas.idMolecule = Molecule.idMolecule
	AND Molecule.Name = "whole"
	
	AND ParamGB.idTraj = Trajectory.idTraj
	AND ParamPhGas.idTraj =  Trajectory.idTraj
	AND Trajectory.Name = "nscm"
	
	AND ParamGB.idPrmtop = prmtop.idPrmtop
	AND prmtop.Name = "mbondi"
	
	AND ParamGB.idIgb = igb.idIgb
	AND igb.Name = "1"
  
ORDER BY MM_PBSA_GB.Frame ASC

Ou bien, l’autre possibilité, serait de faire les 2 requetes suivantes :

  • Requete 1 :

SELECT  MM_PBSA_GB.Frame, MM_PBSA_GB.Gbsur, MM_PBSA_GB.GB
FROM  MM_PBSA_GB, ParamGB, Molecule, Trajectory, prmtop
WHERE  MM_PBSA_GB.idParamGB = ParamGB.idParamGB
	AND ParamGB.idMolecule = Molecule.idMolecule
	AND Molecule.Name = "whole"
	AND ParamGB.idTraj = Trajectory.idTraj
	AND Trajectory.Name = "nscm"
	AND ParamGB.idPrmtop = prmtop.idPrmtop
	AND prmtop.Name = "mbondi"
	AND ParamGB.idIgb = igb.idIgb
	AND igb.idIgb = "1"

et Requete 2 :


SELECT  MM_PBSA_GAS.Frame, MM_PBSA_GAS.Ele, MM_PBSA_GAS.Vdw, MM_PBSA_GAS.Bad
FROM  MM_PBSA_GAS, ParamPhGas, Molecule, Trajectory 
WHERE  MM_PBSA_GAS.idParamPhGas = ParamPhGas.idParamPhGas
	AND ParamPhGas.idMolecule = Molecule.idMolecule
	AND Molecule.Name = "whole"
	AND ParamPhGas.idTraj = Trajectory.idTraj
	AND Trajectory.Name = "nscm"

et de refaire sur ces 2 requetes-la (je ne sais pas comment) un truc du genre


pour requete1.Frame = Requete2.Frame
          toto = MM_PBSA_GAS.Ele + MM_PBSA_GB.GB

Ca aide ?

UP, pour le nouveau titre :paf:

désolé pour le délai, j’était resté sur ma prog Excel (j’essaie de me faire plaindre…)

Tu démarre les jointures sur des requêtes de haut vol! :ouch:
Bon, il faudrait juste 2-3 infos pour voir ce qui manque.
d’abord sur ton schéma
http://www.ibpc.fr/Perso/Nicolas.Guiot/img/DB_Complex_V4.png
qui je le répète est très utile pour voir ce qu’on veut faire, il manque les tables: MM_PBSA_GB, MM_PBSA_GAS
… pour qu’on puisse comprendre ton besoin.
Ensuite, je m’appuis sur ta 1ère Requête, il faudrait faire quelques tests de jointure, pour voir exactement ton contenu de base, et ajouter les jointures progressivement pour voir ce qui ne marche pas. Parcque je dois dire, un jointure sur 8 tables, j’en ai jamais fait, et j’espère bien ne jamais avoir besoin. :stuck_out_tongue:

J’avais dit qu’une jointure complexe pouvait prendre du temps, alors je fais remonter quelques souveneir de cours de SGBD que je ne pense pas trop erronés:
sur tes tables ParamGB, paramPhGas tu utilise des clefs etrangères, (normal, ce sont des tables d’association) et donc chaque jointure peut retourner plus d’un élément. c’est à dire, par exemple, si une molécule a plus d’une trajectoire, (via cette table d’association), la jointure va retourner toutes les trajectoires de cette molécule, et inversement, si pour une trajectoire on a plusieurs molecule, la jointure retourne toutes les molécules de cette trajectoire. Cette exemple s’applique à toutes tes relations n-n (impliqué par les tables d’association)

je suis toujours clair?

C’est pas finit: parcque là ou je veux en venir, c’est que même s’il n’y a que 1000 lignes comme tu le disais, tu peux avoir potentiellement un résultat de 1000 molecules * 1000 trajectoire = 1 000 000 de lignes de résulat, et je ne prend en compte qu’une jointure, comme il y en a 8, on peut imaginer au pire 1000 ^8 = 10^24 lignes de résultat.
ce n’est que le pire des cas, et tu dois être bien en dessous, c’est juste pour illustrer comment des jointure un peu pointues peuvent faire ramer ton serveur.

Tu me dira, oui mais dans le where, je ne sélectionne pas tout, oui, mais suivant l’optimisation du serveur, il peut faire les jointures en priorité, et ensuite sélectionner tes résultats parmis les 10^24 résultats de la jointure. Ce dont je ne suis pas sûr à 100% mais que pichat, mon prof de BDD pourrait peut-être me dire.

Tout ce laius pour introduire l’intérêt de ces quelques tests, et d’une solution éventuelle, mais qui dépend grandement du langage utilisé( dis le nous).

Test 1 jointure impliquée par ParamGB


SELECT  count *
FROM  ParamGB, Molecule, Trajectory, prmtop , igb
WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND ParamGB.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb

ou 
SELECT  ParamGB.idparamGB
FROM  ParamGB, Molecule, Trajectory, prmtop , igb
WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND ParamGB.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb


Test 2 toute la jointure, sans les critères du where


SELECT  MM_PBSA_GB.Frame, MM_PBSA_GAS.Frame , MM_PBSA_GB.GB, MM_PBSA_GAS.Ele

FROM  ParamGB, Molecule, Trajectory, prmtop , igb, ParamPhGas

WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND ParamGB.idMolecule = Molecule.idMolecule
AND ParamPhGas.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamPhGas.idTraj =  Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb
 


Test 3 toute la jointure, sans les critères du where


SELECT  count (*)

FROM  MM_PBSA_GB, MM_PBSA_GAS, ParamGB, Molecule, Trajectory, prmtop , igb, ParamPhGas

WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND MM_PBSA_GB.idParamGB = ParamGB.idParamGB
AND MM_PBSA_GAS.idParamPhGas = ParamPhGas.idParamPhGas
AND ParamGB.idMolecule = Molecule.idMolecule
AND ParamPhGas.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamPhGas.idTraj =  Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb

La taille des ces jointures, (fait plusieurs essai en en enlevant quelque-unes) t’indiqueras un peu la complexité du travaile serveur qu’il y a derrière, et donc le temps de traitement.

Si ça ne passe pas, c’est que ta jointure est trop grosse, ou fausse, est-ce que tu utilise bien les clefs primaires etc.
Peut-être qu’en remontant les jointures portant sur les clef primaires, la réquête sera mieu optimisée.

pour la solution, quand je parlait de séparer en 2 requête, je ne parlait pas de faire une jointure à la main, ou tu regroupe 2 reuqêtes ensembles, non, mais plutôt d’une requête qui te retourne les “ids” correspondant aux résultats ue te cherche, puis une 2ème requête que tu lance pour chaque id, et qui te permet de retrouver tes informations pour affichage. ça fait peut-être pas optimal, mais ça risque d’être plus facile à debugger.

  1. récup 1à n id:

SELECT  ParamGB.idparamGB
FROM  ParamGB, Molecule, Trajectory, prmtop , igb
WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND ParamGB.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb
AND Molecule.Name = "whole"
AND Trajectory.Name = "nscm"
AND prmtop.Name = "mbondi"
AND igb.Name = "1"
 

  1. pour chaque id récup le reste des informations

SELECT  MM_PBSA_GB.Frame, MM_PBSA_GAS.Frame , MM_PBSA_GB.GB, MM_PBSA_GAS.Ele
FROM  MM_PBSA_GB, MM_PBSA_GAS
WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND MM_PBSA_GAS.idParamPhGas = ParamPhGas.idParamPhGas
AND MM_PBSA_GB.idParamGB = 'monIdRecupEn1.'
ORDER BY MM_PBSA_GB.Frame ASC

Pfiou, c’t’écriture, j’espère qu’on aura le courage de me lire. :’(

ya pas de mal…

Alors en fait, les tables MM_PBSA_GB et MM_PBSA_GAS sont sur mon schema respectivement les table GB et PhaseGas

C’est vachement bien explique, j’ai tout compris ce que tu voulais dire (enfin je crois), et je comprends effectivement pourquoi ca peut prendre du tps…

Bon, et maintenant, la partie interessante :

Test 1 jointure impliquée par ParamGB


SELECT  count *
FROM  ParamGB, Molecule, Trajectory, prmtop , igb
WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND ParamGB.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb

ou 
SELECT  ParamGB.idparamGB
FROM  ParamGB, Molecule, Trajectory, prmtop , igb
WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND ParamGB.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb


la 1ere donne une erreur que j’essaie de corriger, mais ca ne donne toujours rien…
J’ai tenté de lancer la 2eme : elle tourne depuis 40 min !!! (sur un Xeon 3 GHz avec 2 Go de RAM).
Elle devrait renvopyer a priori 47 800 enregistrements (enfin si j’ai bien compris…)

tiens, par ici, ca peut etre interessant : http://www.ibpc.fr/Perso/Nicolas.Guiot/img/DB_Snapshot.png

Je teste ca bientot…

Wouah, moi je dis respect surtout d’avoir eu le courage de l’ecrire !!
Bon, sinon, en attendant que je teste la suite, tu trouves ca “normal” que ma requete dure si longtemps ?
(Si c’est le cas, va falloir que je trouve autre chose, pas moyen que ca attende 40 min pour une requete…)

Voila, j’ viens de faire le test 1, et j’ai un truc surprenant :


SELECT  count(*)
FROM  ParamGB, Molecule, Trajectory, prmtop , igb
WHERE   ParamGB.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb

Resultat : 45

L’autre requete :


SELECT  ParamGB.idparamGB
FROM  MM_PBSA_GB, MM_PBSA_GAS, ParamGB, Molecule, Trajectory, prmtop , igb
WHERE  MM_PBSA_GB.Frame = MM_PBSA_GAS.Frame
AND ParamGB.idMolecule = Molecule.idMolecule
AND ParamGB.idTraj = Trajectory.idTraj
AND ParamGB.idPrmtop = prmtop.idPrmtop
AND ParamGB.idIgb = igb.idIgb

Et la, ca fait environ 40 min que la requete tourne (je vais la laisser tourner, on verra cet aprem), .

Bon, voila, j’ai resolu mon pb :
Devant la durée vraiment trop importante que prenait la requete, j’ai opté pour une autre solution :

CREATE TABLE Tp1 (
  Frame int(10) unsigned default NULL,
  Pbsur decimal(10,3) default NULL,
  Pbcal decimal(10,3) default NULL);
  
CREATE TEMPORARY TABLE Tp2 (
	Frame int(10) unsigned default NULL, 
	Ele decimal(10,3) default NULL,
	Vdw decimal(10,3) default NULL,
	Bad decimal(10,3) default NULL);
	

INSERT INTO Tp1 
SELECT  MM_PBSA_PB.Frame, MM_PBSA_PB.Pbsur, MM_PBSA_PB.Pbcal
FROM  MM_PBSA_PB, ParamPB, Molecule, Trajectory, prmtop
WHERE  MM_PBSA_PB.idParamPB = ParamPB.idParamPB
	AND ParamPB.idMolecule = Molecule.idMolecule
	AND Molecule.Name = "whole"
	AND ParamPB.idTraj = Trajectory.idTraj
	AND Trajectory.Name = "nscm"
	AND ParamPB.idPrmtop = prmtop.idPrmtop
	AND prmtop.Name = "mbondi";


INSERT INTO Tp2
SELECT  MM_PBSA_GAS.Frame, MM_PBSA_GAS.Ele, MM_PBSA_GAS.Vdw, MM_PBSA_GAS.Bad
FROM  MM_PBSA_GAS, ParamPhGas, Molecule, Trajectory 
WHERE  MM_PBSA_GAS.idParamPhGas = ParamPhGas.idParamPhGas
	AND ParamPhGas.idMolecule = Molecule.idMolecule
	AND Molecule.Name = "whole"
	AND ParamPhGas.idTraj = Trajectory.idTraj
	AND Trajectory.Name = "nscm";
	

SELECT Tp2.Ele, Tp1.Pbsur
FROM Tp1, Tp2
WHERE Tp1.Frame = Tp2.Frame;

Et ca marche !!!
C’est peut-etre pas tres propre, mais ca fait ce que je demande… c’est tout ce que je voulais

Merci pour tout
++

:clap: :super:
C’est pas forcément une mauvaise solution: on commence par minimiser les données pour avoir un bon modèle, puis on gère des redondances pour optimiser, ce que tu fait.

peut-être que les vues pourraient améliorer ta solution "create view…" (je ne me rappelle plus la syntaxe).