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 :

LEFT JOIN tables retournées incompréhensibles


Sujet :

Requêtes MySQL

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Mars 2017
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Mars 2017
    Messages : 53
    Points : 26
    Points
    26
    Par défaut LEFT JOIN tables retournées incompréhensibles
    Bonjour à tous je suis sur un petit projet où j' ai mis un système de notification en PHP.
    Dans celui-ci j'exécute une requête SQL qui me renvoie le double de valeurs attendues .
    Ayant seulement des bases solides en SQL et n'ayant pas étudié les quelques notions avancées (dont les jointures) , je vous demande votre aide pour réussir à trouver une solution à ce problème qui gêne à l'avancement de mon projet.
    Voici la requête dont je vous ai parlé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $q = $bdd->prepare("SELECT announces.announce_id, notifications.name, notifications.user_email, notifications.seen, notifications.created_at
    FROM notifications 
    LEFT JOIN announces ON announces.announcer_id = announcer_id WHERE subject_email = ? 
    ORDER BY notifications.created_at DESC");
    $q->execute([$_SESSION["profil"]["email"]]);
    Et voici deux images des deux tables concernées par ce problème:

    TABLES announces :
    Nom : announces.db.png
Affichages : 92
Taille : 27,1 Ko
    TABLES notifications :
    Nom : notifications.db.png
Affichages : 91
Taille : 31,1 Ko

    Résultat:
    Nom : result.db.png
Affichages : 94
Taille : 41,1 Ko

    Ce que j'aimerais, c'est seulement récupérer les 3 premières.

    Merci d'avance.

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Ayant seulement des bases solides en SQL et n'ayant pas étudié les quelques notions avancées (dont les jointures)
    Ça c'est rigolo parce que la jointure fait partie des bases du SQL !

    Et de fait, il y a un truc qui semble clocher dans votre jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FROM notifications 
    LEFT JOIN announces ON announces.announcer_id = announcer_id
    Où se trouve la colonne announcer_id dans la table notifications ?

    Avec votre LEFT JOIN, vous souhaitez avoir toutes les lignes de la table notifications et, quand elle existe, la correspondance dans la table announces.
    Est-ce vraiment ce que vous voulez ou bien l'inverse ?

    Bonnes pratiques à adopter :
    1) Dès que vous avez plus d'une table dans une requête, utilisez des alias. Ça rend la l'écriture et la lecture de la requête plus facile.
    2) Comme dans tout programme, aérez et indentez votre code. Là encore, ça rend la lecture, et donc le débogage, plus facile.
    3) Nommez vos tables au singulier. Elles sont en principe issues des entités types du modèle conceptuel de données dont les noms s'écrivent aussi au singulier parce qu'une entité type représente un élément de ce type. Ça permet aussi de lever des ambiguïtés sur le contenu car on pourrait penser qu'une ligne de la table notifications regroupe plusieurs notifications, ce qui contreviendrait à la première forme normale.

    Votre requête devrait plutôt ressembler à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT a.announce_id, n.name, n.user_email, n.seen, n.created_at
    FROM notifications n
    LEFT JOIN announces a ON a.announcer_id = n.[la colonne correspondant à announcer_id dans la table notifications] 
    WHERE n.subject_email = ? 
    ORDER BY n.created_at DESC
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Mars 2017
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Mars 2017
    Messages : 53
    Points : 26
    Points
    26
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Ça c'est rigolo parce que la jointure fait partie des bases du SQL !

    Et de fait, il y a un truc qui semble clocher dans votre jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FROM notifications 
    LEFT JOIN announces ON announces.announcer_id = announcer_id
    Où se trouve la colonne announcer_id dans la table notifications ?
    En effet, il n'y a aucune colonne announce_id. J'ai donc changé la jointure en utilisant une autre table de ma database.
    Votre requête devrait plutôt ressembler à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT a.announce_id, n.name, n.user_email, n.seen, n.created_at
    FROM notifications n
    LEFT JOIN announces a ON a.announcer_id = n.[la colonne correspondant à announcer_id dans la table notifications] 
    WHERE n.subject_email = ? 
    ORDER BY n.created_at DESC
    Je compte utiliser les alias dans mes prochaines requêtes.
    La requete final donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT candidancy.announce_id, notifications.name, notifications.user_email,notifications.seen,notifications.created_at
    FROM notifications 
    LEFT JOIN candidancy 
    ON candidancy.announcer_id = subject_id WHERE subject_email = ? 
    ORDER BY notifications.created_at DESC
    Le résultat :
    Nom : result2.db.png
Affichages : 91
Taille : 15,4 Ko

    les lignes où announce_id = 3 ne devraient pas exister.

    Mais malgré qu'elle fonctionne, j'obtiens toujours un double resultats qui n'a pas lieu d'être.
    Y a t-il un moyen de poffiner la jointure ? Peux-tu m'aider sur ce point?

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT candidancy.announce_id, notifications.name, notifications.user_email,notifications.seen,notifications.created_at
    FROM notifications 
    LEFT JOIN candidancy 
    ON candidancy.announcer_id = subject_id WHERE subject_email = ? 
    ORDER BY notifications.created_at DESC
    Dans quelle table se trouve subject_id ?
    Êtes-vous sûr que announcer_id et subject_id correspondent à la même chose, sémantiquement ?

    Votre requête semble vouloir dire que vous voulez les notifications et, quand elles existent les candidancy correspondant à ces notifications.

    Précédemment, c'était avec les announces. Ce n'est plus le même besoin. Pouvez-vous nous exposer ce besoin en français pour qu'on comprenne ce que vous cherchez à faire ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 392
    Points
    9 392
    Par défaut
    Tu dis que le résultat retourné est incompréhensible. Le résultat retourné est toujours compréhensible, il est conforme à ce que tu as demandé via ta requête.
    Ce qui est incompréhensible, c'est la requête.

    Si je prends la dernière requête :

    Ce serait plus clair (pour toi, pour les gens qui essaient de t'aider, pour tout le monde) si tu écrivais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT candidancy.announce_id, notifications.name, notifications.user_email,notifications.seen,notifications.created_at
    FROM notifications 
    LEFT JOIN candidancy 
    ON candidancy.announcer_id = XXX.subject_id WHERE XXX.subject_email = ? 
    ORDER BY notifications.created_at DESC
    Les colonnes en question, elles proviennent de quelle table... je ne sais pas et je dois remonter loin pour trouver. Alors que ce serait si simple de le dire ici.
    Et si tu trouves que c'est trop long à taper, ou que ça complique la lecture (c'est mon cas, je n'aime pas du tout quand le nom de la table est repris en toutes lettres), il y a les alias. C'est vachement pratique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT c.announce_id, n.name, n.user_email, n.seen, n.created_at
    FROM notifications n
    LEFT JOIN candidancy c
    ON c.announcer_id =  XXX.subject_id WHERE XXX.subject_email = ? 
    ORDER BY n.created_at DESC
    Si à l'arrivée tu obtiens des lignes en double, c'est que dans l'une des 2 tables utilisées, tu as des lignes en double.

    Edit : je vois que Cinéphil a la même question que moi ... Et moi aussi, j'étais surpris de voir une jointure basée sur des noms de colonnes aussi différents.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Mars 2017
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Mars 2017
    Messages : 53
    Points : 26
    Points
    26
    Par défaut
    Voici ma requête complète :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT c.announce_id, n.name, n.user_email, n.seen, n.created_at
    FROM notifications n
    LEFT JOIN candidancy c
    ON c.announcer_id =  n.subject_id WHERE n.subject_email = ? 
    ORDER BY n.created_at DESC
    Précédemment, c'était avec les announces. Ce n'est plus le même besoin. Pouvez-vous nous exposer ce besoin en français pour qu'on comprenne ce que vous cherchez à faire ?
    Concrètement , ce que je cherche à faire, c'est obtenir les notifcations, et si possible l'id de l'annonce pour laquelle il y a eu une candidature où la valeur de notifications.subject_email est égale à celle l'annonceur connecté.

    Voici ma table candidancy actuelle:
    Nom : notifications.PNG
Affichages : 86
Taille : 22,3 Ko
    Et ma table notifications:
    Nom : candidancy.PNG
Affichages : 76
Taille : 12,9 Ko

  7. #7
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 392
    Points
    9 392
    Par défaut
    Il faut un minimum d'organisation, ou de logique.

    Je vais regarder uniquement la table notifications.
    Tu as une colonne subject_Id et une colonne subject_mail. Habituellement, quand on a une colonne qui s'appelle Subject_Id, c'est un Identifiant de Sujet. Et donc pour une valeur de subject Id donnée, toutes les lignes correspondantes devraient avoir le même subject_mail. Un subject_Id, c'est comme un n° de carte bleu, ou un n° de Sécurité sociale. Ca identifie sans ambiguité un individu.

    Tu as le même problème sur les colonnes User_Email et IUser_Id. On s'attend à avoir un User_Id différent pour chaque user_Email nouveau. Et ce n'est pas le cas.

    Ici, tes colonnes Subject_Id et User_Id sont inutilisables, elles vont provoquer des résultats farfelus.

    Ce n'est pas ta requête qui est fausse, c'est l'organisation de ta base de donnée.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Mars 2017
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Mars 2017
    Messages : 53
    Points : 26
    Points
    26
    Par défaut
    En effet à cause de ma base de donnée, je ne peut pas me permettre de récupérer seulement l'email, les annonceurs et les workers sont divisés en deux tables différentes. d’où ces id obligatoires dans la table.

  9. #9
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 392
    Points
    9 392
    Par défaut
    Mais comme ces id ont tous la valeur 1, ça te donne des résultats farfelus.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  10. #10
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Comme tbc, je pense qu'il faut sérieusement revoir la conception de la BDD !
    Un e-mail dans un sujet, déjà, c'est bizarre !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

Discussions similaires

  1. LEFT JOIN qui retourne des valeurs NULL et non NULL
    Par devman2011 dans le forum Langage SQL
    Réponses: 11
    Dernier message: 29/08/2012, 18h05
  2. probleme avec LEFT JOIN multi tables
    Par hinsano dans le forum Langage SQL
    Réponses: 5
    Dernier message: 08/07/2006, 06h36
  3. [Access] Requête avec LEFT JOIN et 3 tables
    Par estelledany dans le forum Langage SQL
    Réponses: 1
    Dernier message: 07/06/2006, 13h27
  4. Réponses: 8
    Dernier message: 11/05/2006, 23h18
  5. left join multiple sur grosses tables
    Par hn2k5 dans le forum Requêtes
    Réponses: 6
    Dernier message: 30/11/2005, 16h10

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