IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Une requete au lieu de 2 ?


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Novembre 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 41
    Par défaut Une requete au lieu de 2 ?
    Bonsoir à tous,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT t1.id_hebergement, t1.id_adherent, t1.genre , t1.name, t1.capacite, t1.label, t1.annonce, t2.genre AS txtgenre, t3.ville 
    FROM tbl_hebergement AS t1 
    INNER JOIN tbl_genre AS t2 ON t1.genre = t2.id_genre 
    INNER JOIN tbl_adresse AS t3 ON t1.id_hebergement = t3.id_hebergement 
    INNER JOIN tbl_adherent AS t4 ON t1.id_adherent = t4.id_adherent 
    WHERE (t1.genre = "1" OR t1.genre ="2") AND t4.actif = 2 
    ORDER BY t3.ville, t1.capacite ASC';
    jusque là pas de problème, seulement parmi ces résultats, j'ai besoin de différencier les id_adherents qui sont également dans la tbl_dispo tout en gardant le classement par t3.ville :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    CREATE TABLE `tbl_dispo` (
      `id_dispo` int(10) unsigned NOT NULL auto_increment,
      `id_hebergement` int(10) unsigned NOT NULL default '0',
      `periode` date NOT NULL default '0000-00-00',
      PRIMARY KEY  (`id_dispo`)
    ) TYPE=MyISAM AUTO_INCREMENT=3 ;
    donc pour l'instant je refais un SELECT dans ma boucle while qui affiche les resultats (PHP)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    while($row = mysql_fetch_array($result))	{
    ...
    $sql = 'SELECT id_dispo FROM tbl_dispo WHERE id_hebergement='.$row['id_hebergement'];
    ...
    if($total) {echo $oui; }else{echo $non;}
    ...
    } // fin du while
    Ce qui est stupide c'est que je n'ai absolument aucun besoin du contenu de la tbl_dispo, (j'en ai besoin par ailleurs, mais pour cette fonction là non...) , j'ai juste besoin de savoir si l'hebergement est dans la tbl_dispo ou pas ...

    je souhaiterais optimiser si possible ce genre de requete, vu que j'en ai d' autres dans le meme style.
    si dans le 1er SELECT je fais un LEFT JOIN sur la tbl_dispo, mes resultats deviennent faux (tbl_dispo.id_hebergement pouvant avoir x entrées tbl_dispo.periode , id_hebergement s'affichera x fois).

    Y a t'il un moyen de traiter tout ca avec une seule requete ? (ou une autre solution en sachant que je ne souhaite pas rajouter un champ a tbl_hebergement qui aurait un rôle de switch (oui/non id_hebergement dans tbl_dispo) c'est une solution que je ne peux pas gerer correctement pour l'instant )

    Merci
    ++

  2. #2
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 288
    Par défaut
    Le plus simple est un LEFT JOIN, mais ça peut générer des doublons (je ne pense pas, mais ça dépend des cardinalités de ton modèle) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT t1.id_hebergement, t1.id_adherent, t1.genre , t1.name, t1.capacite, t1.label, t1.annonce, t2.genre AS txtgenre, t3.ville,
    CASE WHEN  t5.id_hebergement IS NOT NULL THEN 1 ELSE 0 END AS dispo
    FROM tbl_hebergement AS t1 
    INNER JOIN tbl_genre AS t2 ON t1.genre = t2.id_genre 
    INNER JOIN tbl_adresse AS t3 ON t1.id_hebergement = t3.id_hebergement 
    INNER JOIN tbl_adherent AS t4 ON t1.id_adherent = t4.id_adherent 
    LEFT JOIN tbl_dispo AS t5 ON t1.id_adherent = t5.id_hebergement
    WHERE t1.genre IN ('1', '2) AND t4.actif = 2 
    ORDER BY t3.ville, t1.capacite ASC';
    Par ailleurs, je te conseille fortement d'utiliser des alias de table plus explicites que t1, t2, etc. Avec par exemple H pour tbl_hebergement, G pour tbl_genre, etc., on fait bcp moins de coquilles.

  3. #3
    Membre averti
    Inscrit en
    Novembre 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 41
    Par défaut
    Citation Envoyé par Antoun Voir le message
    Le plus simple est un LEFT JOIN, mais ça peut générer des doublons (je ne pense pas, mais ça dépend des cardinalités de ton modèle) :
    Et bien si justement ca me renvoie les doublons
    Des adhérents a un OT propose en location de vacances n hébergements et parmi ces hébergements , a l'instant T, certains ont n jours de disponibilité (tbl_dispo.periode) et d'autres pas pour x raisons
    donc si l'id_hebergement 1 a 260 jours de disponibilités aujourd'hui il m'affiche 260 x 1 avec un LEFT JOIN

    Néanmoins, je retiens "CASE WHEN ... IS NOT NULL THEN 1 ELSE 0 END AS ..." qui va me servir pour une autre requête ou je n'aurai pas de problème de doublon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT t1.id_hebergement, t1.id_adherent, t1.genre , t1.name, t1.capacite, t1.label, t1.annonce, t2.genre AS txtgenre, t3.ville,
    CASE WHEN  t5.id_hebergement IS NOT NULL THEN 1 ELSE 0 END AS dispo
    FROM tbl_hebergement AS t1 
    INNER JOIN tbl_genre AS t2 ON t1.genre = t2.id_genre 
    INNER JOIN tbl_adresse AS t3 ON t1.id_hebergement = t3.id_hebergement 
    INNER JOIN tbl_adherent AS t4 ON t1.id_adherent = t4.id_adherent 
    LEFT JOIN tbl_dispo AS t5 ON t1.id_adherent = t5.id_hebergement
    WHERE t1.genre IN ('1', '2) AND t4.actif = 2 
    ORDER BY t3.ville, t1.capacite ASC';
    Et pourquoi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LEFT JOIN tbl_dispo AS t5 ON t1.id_adherent = t5.id_hebergement
    ? y'a pas de relation adhérent/dispo, il y a une raison particulière ou c'est une coquille (cela étant j'ai refais la requête avec t1.id_hebergement = t5.id_hebergement et j'ai les mêmes resultats)

    Merci
    ++

  4. #4
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 288
    Par défaut
    Citation Envoyé par Jean Fi Voir le message
    Et bien si justement ca me renvoie les doublons
    Des adhérents a un OT propose en location de vacances n hébergements et parmi ces hébergements , a l'instant T, certains ont n jours de disponibilité (tbl_dispo.periode) et d'autres pas pour x raisons
    donc si l'id_hebergement 1 a 260 jours de disponibilités aujourd'hui il m'affiche 260 x 1 avec un LEFT JOIN
    Logique. Dans ce cas, on va le refaire avec une sous-requête EXISTS plutôt qu'en jointure externe.
    Citation Envoyé par Jean Fi Voir le message
    Néanmoins, je retiens "CASE WHEN ... IS NOT NULL THEN 1 ELSE 0 END AS ..." qui va me servir pour une autre requête ou je n'aurai pas de problème de doublon
    En fait une simple expression booléenne comme ... IS NOT NULL donnerait exactement le même résultat. Par contre c'est spécifique à MySQL ; la plupart des SGBD refuseraient cette écriture alors qu'ils accepteraient le CASE WHEN.
    Citation Envoyé par Jean Fi Voir le message
    Et pourquoi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LEFT JOIN tbl_dispo AS t5 ON t1.id_adherent = t5.id_hebergement
    ? y'a pas de relation adhérent/dispo, il y a une raison particulière ou c'est une coquille (cela étant j'ai refais la requête avec t1.id_hebergement = t5.id_hebergement et j'ai les mêmes resultats)
    Coquille. J'ai un peu confondu les adhérents et les hébergements.

    Au final, ça donne donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT t1.id_hebergement, t1.id_adherent, t1.genre , t1.name, t1.capacite, t1.label, t1.annonce, t2.genre AS txtgenre, t3.ville,
    CASE 
      WHEN EXISTS (SELECT 1 FROM tbl_dispo AS t5 WHERE t3.id_hebergement = t5.id_hebergement) 
      THEN 1
      ELSE 0 
      END AS dispo
    FROM tbl_hebergement AS t1 
    INNER JOIN tbl_genre AS t2 ON t1.genre = t2.id_genre 
    INNER JOIN tbl_adresse AS t3 ON t1.id_hebergement = t3.id_hebergement 
    INNER JOIN tbl_adherent AS t4 ON t1.id_adherent = t4.id_adherent 
    WHERE t1.genre IN ('1', '2) AND t4.actif = 2 
    ORDER BY t3.ville, t1.capacite ASC';

  5. #5
    Membre averti
    Inscrit en
    Novembre 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 41
    Par défaut
    Merci...
    je peux pas dire si ca marche ......
    j'ai un peu oublié de ....
    signaler que j'etais sous Mysql 4.0.x

    Mais bon, je vais me debrouiller de passer en v5 tres rapidement, peut etre meme cette nuit, parceque ca commence a me gaver grave cette histoire de pas pouvor faire de sous requete
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CASE 
      WHEN EXISTS (SELECT 1 FROM tbl_dispo AS t5 WHERE t3.id_hebergement = t5.id_hebergement) 
      THEN 1
      ELSE 0 
      END AS dispo
    le "1" c'est quoi ? ca veut dire que je lui demande de chercher "quelquechose d'indefini mais quelquechyose" sous la condition t3.id=t5.id ? on peut faire des trucs comme ça ?

  6. #6
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 288
    Par défaut
    Citation Envoyé par Jean Fi Voir le message
    Merci...
    je peux pas dire si ca marche ......
    j'ai un peu oublié de ....
    signaler que j'etais sous Mysql 4.0.x
    bah alors je peux te le dire, ça ne marche pas
    Citation Envoyé par Jean Fi Voir le message
    le "1" c'est quoi ? ca veut dire que je lui demande de chercher "quelquechose d'indefini mais quelquechyose" sous la condition t3.id=t5.id ? on peut faire des trucs comme ça ?
    ça veut dire : je m'en fous de ce qui est renvoyé, je veux juste savoir si qqch est renvoyé ou pas. Donc autant que ce qui soit renvoyé soit le plus économique possible. La constante 1 répond bien à cette exigence !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2010] faire une requete au lieu d'une seule
    Par moimemessssssssss dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 28/02/2014, 00h22
  2. Une requete Sql au lieu de trois vues
    Par ensi7 dans le forum Langage SQL
    Réponses: 6
    Dernier message: 30/08/2007, 12h38
  3. [syntaxe] Gerer les variables dans une requete
    Par rastapopulos dans le forum MS SQL Server
    Réponses: 12
    Dernier message: 15/04/2003, 12h53
  4. [VB6] [Excel] Résultat d'une requete ds une feuille
    Par elifqaoui dans le forum VB 6 et antérieur
    Réponses: 12
    Dernier message: 07/01/2003, 17h52
  5. Créer une vue pour trier une requete UNION ?
    Par Etienne Bar dans le forum SQL
    Réponses: 3
    Dernier message: 03/01/2003, 20h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo