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 :

Limiter un LEFT JOIN à un seul résultat


Sujet :

Requêtes MySQL

  1. #1
    Membre actif Avatar de bigsister
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2002
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2002
    Messages : 314
    Points : 265
    Points
    265
    Par défaut Limiter un LEFT JOIN à un seul résultat
    Bonjour à tous,

    Voilà mon problème :
    J'ai une table A avec 1 000 lignes.
    Ma table A n'a qu'un champ "id"

    J'ai une table B avec 1 000 000 de lignes.
    Ma table B a 2 champs "id" et "date"

    à 1 enregistrement de A peuvent correspondre N enregistrements de B.

    Je souhaiterais simplement afficher dans une page tous mes A.id, suivis d'une seule date trouvée dans B (la première trouvée):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT A.id, B.date
    FROM A LEFT JOIN B ON A.id = B.id
    GROUP BY A.id
    Le problème c'est qu'en faisant cela, étant donné que pour un id dans A je peux avoir une correspondance avec 50 000 enregistrements dans B... ma requête rame...
    J'ai pas mal cherché mais je n'ai pas trouvé de solution pour le moment...

    Quelqu'un aurait une idée ?

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    "La première trouvée" implique forcément un ordre donc "première trouvée" par rapport à quoi ?

    Sinon la solution est dans l'utilisation d'un group by : http://sqlpro.developpez.com/cours/sqlaz/ensembles/

    Et deuxième remarque, si la date jointe n'a pas d'importance, pourquoi la ramener ?

  3. #3
    Membre actif Avatar de bigsister
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2002
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2002
    Messages : 314
    Points : 265
    Points
    265
    Par défaut
    La date a de l'importance mais je ne récupère que la première trouvée dans ma table car en principe c'est la plus ancienne (la première insérée) et c'est ça qui m'intéresse.
    Le group by réduit le résultat final, mais il n'empêche pas MySQL de parcourir tous les enregistrements...
    Le lien que tu m'as donné est intéressant mais il me semble déjà avoir envisagé tout ça

  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
    La plus ancienne date => MIN(la_colonne_date)
    Avec le GROUP BY indiqué par vmolines, tu devrais t'en sortir...
    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
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Citation Envoyé par bigsister Voir le message
    La date a de l'importance mais je ne récupère que la première trouvée dans ma table car en principe c'est la plus ancienne (la première insérée) et c'est ça qui m'intéresse.
    Le group by réduit le résultat final, mais il n'empêche pas MySQL de parcourir tous les enregistrements...
    Le lien que tu m'as donné est intéressant mais il me semble déjà avoir envisagé tout ça
    Il est évident que si vous allez chercher des données dans la table jointe, les lignes seront lues. Vous ne pouvez dire que vous souhaitez ces données et en même temps vouloir que le SGBD ne les lise pas...

    Vous pouvez optimiser ces lectures en indexant les colonnes utilisées dans le group by notamment. Pour plus de détail, référez vous à la doc de MySQL : http://dev.mysql.com/doc/refman/5.1/...imization.html

  6. #6
    Membre actif Avatar de bigsister
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2002
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2002
    Messages : 314
    Points : 265
    Points
    265
    Par défaut
    Il est évident que si vous allez chercher des données dans la table jointe, les lignes seront lues. Vous ne pouvez dire que vous souhaitez ces données et en même temps vouloir que le SGBD ne les lise pas...
    Je veux bien qu'il fasse ma jointure mais qu'il se limite au premier résultat dans ma table B...

    Je n'ai toujours pas trouvé de solution. Le group by me renverra bien ce que je veux mais le problème c'est que MySQL va lire toutes mes correspondances dans B...

  7. #7
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Si vous suivez les conseils d'optimisation de la clause Group By, un index pourra être utilisé et limiter les lectures au minimum.

    Pour optimiser vos requêtes il va falloir apprendre à utiliser la commande Explain qui permet de voir le plan d'exécution utilisé par le SGBD pour traiter votre requête : http://dev.mysql.com/doc/refman/5.1/...g-explain.html

  8. #8
    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
    Citation Envoyé par bigsister Voir le message
    Je veux bien qu'il fasse ma jointure mais qu'il se limite au premier résultat dans ma table B...

    Je n'ai toujours pas trouvé de solution. Le group by me renverra bien ce que je veux mais le problème c'est que MySQL va lire toutes mes correspondances dans B...
    Pourquoi t'inquiètes-tu pour ça ?
    1 million de lignes, ce n'est pas encore énorme pour un SGBD. J'ai travaillé avec des tables de plusieurs dizaines de millions de lignes en jointure avec un temps de réponse tout à fait satisfaisant.

    Si tu mets un index sur la colonne de date, il va utiliser l'index pour trouver très rapidement la date mini.
    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 !

  9. #9
    Membre actif Avatar de bigsister
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2002
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2002
    Messages : 314
    Points : 265
    Points
    265
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Pourquoi t'inquiètes-tu pour ça ?
    1 million de lignes, ce n'est pas encore énorme pour un SGBD. J'ai travaillé avec des tables de plusieurs dizaines de millions de lignes en jointure avec un temps de réponse tout à fait satisfaisant.

    Si tu mets un index sur la colonne de date, il va utiliser l'index pour trouver très rapidement la date mini.
    En théorie oui, mais en pratique ma page met 2 min à s'afficher...

  10. #10
    Membre actif Avatar de bigsister
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2002
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2002
    Messages : 314
    Points : 265
    Points
    265
    Par défaut
    Apparemment c'est un problème récurrent que je suis loin d'être le seul à rencontrer... Ca semble basique et pourtant... pour résumer : comment limiter la selection à un seul enregistrement à droite quand on utilise un LEFT JOIN...

    Si ça peut aider à me comprendre :
    J'ai 1 000 clients qui ont chacun 1 000 connexions d'enregistrées.
    Je veux afficher un tableau avec les 1 000 clients et pour chacun la date de la première connexion... sachant que je n'ai pas d'index sur mon champs date (je ne peux pas) mais qu'à priori la première ligne que MySQL trouvera pour chaque client sera la bonne...

  11. #11
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    GROUP BY sur les colonnes de la table de gauche et une fonction d'agrégat sur la colonne de la table de droite...

  12. #12
    Membre actif Avatar de bigsister
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2002
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2002
    Messages : 314
    Points : 265
    Points
    265
    Par défaut
    Citation Envoyé par vmolines Voir le message
    GROUP BY sur les colonnes de la table de gauche et une fonction d'agrégat sur la colonne de droite...
    Si j'ai une fonction d'agrégat sur la colonne de droite c'est bien qu'il doit parcourir tous les enregistrements de droite pour faire l'agrégation (MAX, MIN etc..)... non ?

  13. #13
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Et moi aussi j'ai du mal à me faire comprendre.

    Comment le SGBD peut dire que c'est la première connexion s'il ne compare pas toutes les dates de connexion ?

    Deuxio, dire qu'on ne peut pas mettre un index quand on a une requête qui rame à cause de ce manque, c'est juste stupide. Alors peut être que vous ne pouvez pas à votre échelle mais ça reste stupide

  14. #14
    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
    Citation Envoyé par bigsister Voir le message
    sachant que je n'ai pas d'index sur mon champs date (je ne peux pas)
    Ben t'es mal barré !
    Pourquoi tu ne peux pas ?
    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 !

  15. #15
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Dans mon petit parcours, j'ai été surpris de la quantité d'arguments qu'on a pu me donner pour mal faire les choses .

  16. #16
    Membre actif Avatar de bigsister
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2002
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2002
    Messages : 314
    Points : 265
    Points
    265
    Par défaut
    vmolines c'est pas très sympa... je ne suis pas un débutant non plus. Disons qu'en l'état actuel de mon système, rajouter un index sur des millions d'enregistrements à chaud présente un risque de crash de MySQL (J'en ai déjà fait l'expérience)...

    Donc OK, ne pas avoir d'index sur un champ de recherche c'est un peu dommage mais pour l'instant je ne peux pas mieux faire sans interrompre le service... d'autant que c'est la seule requête qui nécessite vraiment cet index (donc pas critique à priori).

  17. #17
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Citation Envoyé par bigsister Voir le message
    vmolines c'est pas très sympa... je ne suis pas un débutant non plus. Disons qu'en l'état actuel de mon système, rajouter un index sur des millions d'enregistrements à chaud présente un risque de crash de MySQL (J'en ai déjà fait l'expérience)...

    Donc OK, ne pas avoir d'index sur un champ de recherche c'est un peu dommage mais pour l'instant je ne peux pas mieux faire sans interrompre le service... d'autant que c'est la seule requête qui nécessite vraiment cet index (donc pas critique à priori).
    Je ne suis pas là pour être sympa mais pour t'aider dans la résolution de ton problème.

    Désolé si les solutions que je propose ne sont pas sympas et si MySQL crashe sur la création d'un index.

  18. #18
    Membre averti
    Homme Profil pro
    Consultant PLM
    Inscrit en
    Août 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Consultant PLM

    Informations forums :
    Inscription : Août 2007
    Messages : 203
    Points : 304
    Points
    304
    Par défaut
    A tout hasard :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT id, MIN(date)
    FROM B
    GROUP BY id
    Tu n'as pas besoin de la jointure dans le cas que tu exposes. A priori, pour 1,000,000 d'enregistrements, ça devrait aller très vite avec cette requête.

  19. #19
    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
    C'est ce qu'on lui dit depuis le début mais il s'obstine à vouloir éviter que toute la table soit parcourue sans mettre d'index sur la colonne de date, ce qui est impossible pour trouver la date mini de chaque valeur de regroupement.
    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 !

  20. #20
    Membre actif Avatar de bigsister
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2002
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2002
    Messages : 314
    Points : 265
    Points
    265
    Par défaut
    bhamp0 j'ai 2 tables donc sans jointure pas possible

    Cinephil, à la base je m'en fous du MIN(date) je veux le premier enregistrement qu'il rencontre dans la table B car je sais que ce sera le MIN.
    Je n'utilise justement pas cette fonction MIN pour ne pas parcourir ma table sur un champ qui n'est pas indexé comme tu l'as dis...

    Après soit je me fait mal comprendre soit je suis à côté de la plaque sur ce coup là et c'est moi qui ne vous comprends pas... donc je posterai quand j'aurai trouvé.

    Merci quand même !

Discussions similaires

  1. Left join avec les résultats des trois requêtes
    Par ghatfan99 dans le forum Débuter
    Réponses: 2
    Dernier message: 01/07/2011, 10h28
  2. Limit dans la jointure de droitre (LEFT JOIN)
    Par le_binr dans le forum Langage SQL
    Réponses: 2
    Dernier message: 21/07/2009, 16h05
  3. left outer join et mauvais résultat
    Par bastien dans le forum Requêtes
    Réponses: 2
    Dernier message: 26/03/2009, 11h30
  4. Left join et les limites
    Par snoop-tom dans le forum Requêtes
    Réponses: 7
    Dernier message: 06/01/2009, 15h39
  5. un left join ne me donne pas le résultat attendu
    Par kikidrome dans le forum Requêtes et SQL.
    Réponses: 10
    Dernier message: 05/12/2008, 16h58

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