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 :

utilisation de "not exist"


Sujet :

Requêtes MySQL

  1. #1
    Membre à l'essai
    Inscrit en
    Mars 2008
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 16
    Points : 10
    Points
    10
    Par défaut utilisation de "not exist"
    Bonsoir,

    J'ai besoin d'utiliser la "clause" "not exists" pour une requête sql mais je ne
    voie pas très bien comment m'y prendre (en fait je ne suis pas vraiment
    sure que cela soit possible dans mon cas car j'ai l'impression qu'il me
    manque quelque chose... ni même que l'utilisation de la clause "not exists"
    soit la bonne solution).

    J'ai une base pour gérer, entre autre, l'occupation de salles de réunion.
    Elle contient :
    *une table "salle" qui contient entre autre
    => une référence de salle
    *une table "calendrier" où sont stockées les plannings d'occupation des salles.
    La table calendrier contient (entre autre) :
    => une référence de salle
    => un champ mois
    => un champ année
    => un champ jours qui est une string de 31 caractères. Chacun des
    caractères représente un des jours du mois (la durée des mois est gérée autre part).
    si le caractère est "0" => salle libre ce jour là
    si le caractère est "1" => salle occupée ce jour là.

    Les enregistrements sont créés à la volée par un script php (avec le champ jours initialisé à la valeur
    0000000000000000000000000000000 : soit 31 zéros).
    Mon problème est le suivant : lorsque j'interroge ma base (requête sur le calendrier), pour connaitre
    la disponibilité des salles, je ne récupère que les références de salles dont
    le planning a été créé (ce qui est tout à fait normal). Mais en fait il faudrait
    aussi que je récupère les références des salles qui n'ont pas de calendrier
    (pour un mois et une année donnée) parce que cela veut dire que le planning est vide,
    donc que la salle est disponible. Est-il possible d'utiliser, par exemple, la liste de toutes les références
    des salles (en faisant une requête sur la table salle) et de m'en servir pour vérifier que la table calendrier
    n'existe pas?? Et combiner cette requête avec une requête "classique" de recherche sur le champ jours
    pour obtenir la liste globale des salles libres sur une période donnée?

    Même si j'ai fait de mon mieux pour décrire mon problème, je ne suis pas bien sure de la lisibilité
    de mon post Alors merci pour votre patience et votre indulgence

    Merci pour votre aide,
    Cordialement,

    -Xirom-

  2. #2
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Saluton,
    En fait il te faut faire une jointure externe (LEFT JOIN) entre la table salles et la table calendrier et filtrer sur la colonne jours avec ton masque LIKE '_____0%' (par exemple) OR jours IS NULL. Bien sûr, tu filtres aussi sur la colonne année et mois.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  3. #3
    Expert confirmé

    Homme Profil pro
    SDE
    Inscrit en
    Août 2007
    Messages
    2 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : SDE

    Informations forums :
    Inscription : Août 2007
    Messages : 2 013
    Points : 4 324
    Points
    4 324
    Par défaut
    Bonjour,

    Citation Envoyé par Maljuna Kris Voir le message
    Saluton,
    En fait il te faut faire une jointure externe (LEFT JOIN) entre la table salles et la table calendrier
    Tout à fait

    Citation Envoyé par Maljuna Kris Voir le message
    et filtrer sur la colonne jours avec ton masque LIKE '_____0%' (par exemple) OR jours IS NULL. Bien sûr, tu filtres aussi sur la colonne année et mois.
    Cela peut-être une solution, on pourrait aussi créer une fonction utilisateur pour retourner le numéro du jour, cela serait plus pratique, mais pas indispensable.

    @xirom : peut-tu nous passer plus amples informations, c'est-à-dire le modèle logique et la forme du retour de la requête, il sera plus facile pour nous te mettre sur la voie.
    http://alaindefrance.wordpress.com
    Certifications : SCJP6 - SCWCD5 - SCBCD5 - SCMAD1
    SDE at BitTitan

  4. #4
    Membre à l'essai
    Inscrit en
    Mars 2008
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 16
    Points : 10
    Points
    10
    Par défaut
    Bonjour,

    Et tout d'abord merci pour vos réponses et l'intérêt que vous portez à mon problème!


    Citation Envoyé par kazou Voir le message
    @xirom : peut-tu nous passer plus amples informations, c'est-à-dire le modèle logique et la forme du retour de la requête, il sera plus facile pour nous te mettre sur la voie.
    voici le contenu de mes tables (la table salle contient plus de champs mais ils ne sont pas utilisés dans le cas présent) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    table salle
    id  	int(11)  	 	  	
    id_proprietaire int(11) 	
    disponible 	int(11) 			
    designation 	varchar(255) 
    ...
    => le champ "id_propriétaire" correspond au département auquel est
    rattaché la salle

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    table calendrier
    id  	int(11)  
    annee 	int(11) 	
    mois 	int(11) 	
    jours 	varchar(31)
    => le champ "id" correspond à l'id de la salle.

    donc voici comment je procède :

    1- j'ai un formulaire php qui me permet d'interroger ma base de la façon suivante : j'indique juste une date de début et de fin de période (format jj/mm/aaaa) dans mon formulaire php, je les récupère et je créé à partir de cela une variable "jourrecherche" correspondant à la chaine recherchée (=période recherchée. Pour l'instant je travaille juste sur un même mois mais il faudra bien sur que je généralise ma recherche!!!) :

    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    // dateDebut et dateFin sont au format jj/mm/aaaa
    if (isset($_POST['dateDebut'])) $dateDebut = $_POST['dateDebut'];
    	else $dateDebut = '';
    if (isset($_POST['dateFin'])) $dateFin = $_POST['dateFin'];
    	else $dateFin = '';
    if (isset($_POST['type_location'])) $type_location = $_POST['type_location'];
    	else $type_location = '';
     
    list($daydeb, $monthdeb, $yeardeb) = split('[/.-]', $dateDebut);
    list($dayfin, $monthfin, $yearfin) = split('[/.-]', $dateFin);
     
    if($yeardeb==$yearfin and $monthdeb==$monthfin)
     {
      $jourdeb=$jourlibre=$jourfin="";
      for($i=1;$i<=31;$i++)
      {
       if($i<$dateDebut) $jourdeb=$jourdeb."_";
       if($i>=$dateDebut and $i<=$dateFin) $jourlibre=$jourlibre."0";
       if($i>$dateFin) $jourfin=$jourfin."_";
      }
      $jourrecherche=$jourdeb.$jourlibre.$jourfin;

    Après j'interroge la table calendrier pour récupérer toutes les salles dispo :

    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $query="select id,annee,mois from calendrier where annee='$yeardeb' and mois='$monthdeb' and jours like '$jourrecherche'";
    $result = mysql_query($query) or $this->errmysql($this->query);

    ==> le problème est qu'à ce niveau là, je ne récupère pas les identifiants
    des salles si le "calendrier du mois" (le planning du mois qui correspond à une entrée dans la table calendrier) n'a pas été créé (car il est créé à la volée via php à un autre endroit...).

    et j'ajoute une requète supplémentaire dans le while pour récupérer les
    les identifiants des salles dispo (et là je me demande, s'il vaut mieux faire un "join" quelque part?? mon problème est que les requêtes doivent très rapides car actuellement on a une usine à gaz et ça plante tout le temps à cause de requêtes monstrueuses )

    voici le code du "while avec requète" :

    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
           $id=$row[0];
           $query2="select * from salle where id='$id'";
           $result2 = mysql_query($query2) or $this->errmysql($this->query);
           while ($row2 = mysql_fetch_array($result2, MYSQL_NUM)) {
              echo "id=".$id."designation=".$row2[4]);
            }
     }

    Voilà, j'espère que j'ai correctement répondu... et aussi que j'ai utilisé les balises code à bon escient et que la description est conforme aux normes du forum Sinon désolé... suis pas du tout spécialiste en BD donc je connais pas le formalisme...

    Merci encore pour votre aide,

    Cordialement,

    -Xirom-

  5. #5
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Je crois t'avoir donné une réponse t'invitant à faire
    une jointure entre les deux tables, salle et calendrier et filtrer sur la colonne jours avec ton masque LIKE '_____0%' (par exemple) OR jours IS NULL
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  6. #6
    Membre à l'essai
    Inscrit en
    Mars 2008
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 16
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par Maljuna Kris Voir le message
    Saluton,
    En fait il te faut faire une jointure externe (LEFT JOIN) entre la table salles et la table calendrier et filtrer sur la colonne jours avec ton masque LIKE '_____0%' (par exemple) OR jours IS NULL. Bien sûr, tu filtres aussi sur la colonne année et mois.
    Re-bonjour,

    oui oui, j'ai bien noté cela!
    Et d'ailleurs cela m'a rappelé que 'join' existait (j'avais oublié!!!!)...
    Donc j'essaye d'implanter cela... Mais pour l'instant je patoge un peu...
    Je vous donne des news dès que j'ai avancé!!!

    En tous cas merci bien pour ton aide Maljuna Kris!

    Cordialement,

    -Xirom-

  7. #7
    Membre à l'essai
    Inscrit en
    Mars 2008
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 16
    Points : 10
    Points
    10
    Par défaut
    Re-re-bonjour,

    Bon alors j'ai finalement réussi à écrire une requête avec le "join", et cela
    fonctionne très bien!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    -- Requête appelée dans un script PHP
     
    SELECT salle.id, salle.designation, salle.disponible 
    FROM salle LEFT JOIN calendrier 
    ON salle.id=calendrier.id
    where salle.disponible=1 
      and calendrier.mois='$monthdeb' and calendrier.annee='$yeardeb' 
      and calendrier.jours like '$jourrecherche'  ORDER BY salle.id;
    Merci!!

    Par contre, je ne peux pas utiliser 'IS NULL' (sur le champ jours) car en fait ce n'est pas seulement
    mon champ "jours" qui n'est pas renseigné, mais l'enregistrement entier qui n'existe pas dans la table calendrier
    => par défaut si l'enregistrement n'existe pas cela veut dire que la salle est disponible.
    Du coup je ne sais pas comment faire pour filtrer
    Est-ce possible???

    Merci encore pour votre aide!

    Cordialement,

    -Xirom-

  8. #8
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Citation Envoyé par xirom Voir le message
    Par contre, je ne peux pas utiliser 'IS NULL' (sur le champ jours) car en fait ce n'est pas seulement
    mon champ "jours" qui n'est pas renseigné, mais l'enregistrement entier qui n'existe pas dans la table calendrier
    Et alors ? Qui peut le plus peut le moins. La jointure LEFT JOIN laissera passer les salles qui n'ont pas de réservation du tout comme celles qui n'ont pas de réservation ce jour-là.
    Par contre du dois mettre un DISTINCT après le SELECT si tu ne veux pas ramasser une palanquée de doublons.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  9. #9
    Membre à l'essai
    Inscrit en
    Mars 2008
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 16
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par Maljuna Kris Voir le message
    Et alors ? Qui peut le plus peut le moins. La jointure LEFT JOIN laissera passer les salles qui n'ont pas de réservation du tout comme celles qui n'ont pas de réservation ce jour-là.
    Par contre du dois mettre un DISTINCT après le SELECT si tu ne veux pas ramasser une palanquée de doublons.
    Bonjour,

    En fait lorsque j'ai publié le message j'avais testé la requête et cela ne
    fonctionne pas. Et je pense que c'est parce que l'enregistrement dans
    le calendrier n'existe pas :

    par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    table calendrier
    --------------------------------------------------------------
    | id  |   mois  |   an    |  jours                           |
    --------------------------------------------------------------
    |  1  |    10    |   2008 |  0000000000000000000000000000000 |
    |  1  |    11    |   2008 |  1100000000000000000000000000000 |
    |  2  |    10    |   2008 |  0000011000000000000000000000000 |
    |  2  |    11    |   2008 |  1100000000000000000000000000000 |
    |  2  |    12    |   2008 |  0000000000000000000000000000000 |
    --------------------------------------------------------------
    ==> si je cherche les salles qui sont disponibles tout le mois de
    décembre 2008, je ne récupère pas la salle "1" car il n'existe pas
    de d'entrée pour le mois "12" / an "2008" dans le calendrier
    pour le mois de décembre.

    Cordialement,

    -Xirom-

  10. #10
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT DISTINCT salle.id, salle.designation, salle.disponible 
                FROM salle LEFT JOIN calendrier 
                ON salle.id=calendrier.id 
                WHERE salle.disponible=1 
                  AND (
                          (calendrier.mois='$monthdeb' 
                          AND calendrier.annee='$yeardeb' 
                          AND calendrier.jours LIKE'$jourrecherche')
                         OR calendrier.jours IS NULL
                         )
      ORDER BY salle.id;
    Soit il y a des réservations, soit (OR) il n'y en a pas (IS NULL), dans tous les cas je récupère la salle.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  11. #11
    Membre à l'essai
    Inscrit en
    Mars 2008
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 16
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par Maljuna Kris Voir le message
    Soit il y a des réservations, soit (OR) il n'y en a pas (IS NULL), dans tous les cas je récupère la salle.
    Bonsoir,

    J'ai testé cette requête et je ne récupère toujours pas les salles dont le calendrier n'est pas rempli.
    Donc j'ai fait le test directement sur phpmyadmin pour vérifier la jointure.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT sa.id, sa.designation, sa.disponible, cal.annee, cal.mois, cal.jours
    FROM salle sa
    LEFT JOIN calendrier cal ON sa.id = cal.id
    WHERE sa.disponible =1
    ORDER BY sa.id
    et voici un extrait du résultat de cette jointure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    id 	designation 	dispo	annee 	mois 	jours
    --------------------------------------------------------------------------------
    2 	reunion-rouge 	1 	2005 	5 	0000000003333333333333333333333
    2 	reunion-rouge 	1 	2005 	6 	3333300000000000000000000000000
    2 	reunion-rouge 	1 	2005 	10 	0000000001111111111110000000000
    2 	reunion-rouge 	1 	2005 	12 	0000000000022222200000000000000
    2 	reunion-rouge 	1 	2006 	1 	2222222222222222222222222222222
    2 	reunion-rouge 	1 	2006 	2 	2222222222222222222222222222000
    2 	reunion-rouge 	1 	2006 	3 	2222222222222222222222222222222
    2 	reunion-rouge 	1 	2006 	4 	2222222222222222222222222222220
    2 	reunion-rouge 	1 	2006 	5 	2222222222222222222222222222222
    2 	reunion-rouge 	1 	2006 	6 	2222222222222222222222222222220
    =>aucun enregistrement pour juillet, août, septembre 2005 etc.

    ==> le problème est que l'enregistrement n'existe pas dans le calendrier.

    Par contre, cela me permet de récupérer les salles qui n'ont aucune entrée dans le calendrier,
    car à ce moment là, lors de la création de la jointure, les champs du calendrier sont initialisés à "NULL".

    Illustration :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM calendrier
    WHERE id =187
    ==> aucun enregistrement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT sa.id, sa.designation, sa.disponible, cal.annee, cal.mois, cal.jours
    FROM salle sa
    LEFT JOIN calendrier cal ON sa.id = cal.id
    WHERE sa.id =187
    ORDER BY sa.id
    résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    id 	designation 	disponible 	annee 	mois 	jours
    -------------------------------------------------------------
    187 	salle-chopin 	1 	        NULL 	NULL  NULL
    Cordialement,

    -Xirom-

  12. #12
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    C'était prévisible sauf que jusqu'à là ta projection n'intégrait pas de colonnes de la table calendrier. Si pour une salle tu n'as aucun enregistrement de réservation pour le mois, tu récupèreras toujours au moins un enregistrement avec les données de la salle et les 3 colonnes de réservation à NULL.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

Discussions similaires

  1. Réponses: 6
    Dernier message: 31/07/2009, 21h43
  2. Utilisation de EXISTS ou NOT EXISTS
    Par lucky31 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 31/05/2006, 16h43
  3. PROBLEME AVEC LES REQUETES IS NULL / NOT EXISTS
    Par sylvaine dans le forum Langage SQL
    Réponses: 5
    Dernier message: 04/06/2004, 13h26

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