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

Langage SQL Discussion :

SELECT avec un ordre dépendant d'entrées dans une autre table.


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 9
    Par défaut SELECT avec un ordre dépendant d'entrées dans une autre table.
    J'ai deux tables

    'people' (avec id, nom et compagnie)
    'event' (avec about_id (correspondant aux id des 'people'), date, type, ...)

    Je veux faire deux options de tri :

    - Une requête qui select tous les 'people', en les triant par DATE de l''event' le plus récent qui leur soit associé, sachant qu'il peut évidemment y avoir plusieurs 'event' pour un 'people'.

    - Une requête qui select tous les 'people', en les triant par TYPE de l''event' le plus récent qui leur soit associé.

    En gros il faudrait que je fasse un select du genre
    "... ORDER BY (le event.date du plus récent des event dont event.about_id=people.id)"
    et
    "... ORDER BY (le event.type du plus récent des event dont event.about_id=people.id)"

    en bref ... help ?

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Qu'avez-vous commencé à écrire ?

  3. #3
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    Une requête peut être composée des clauses :
    SELECT
    FROM
    JOIN
    WHERE
    GROUP BY
    HAVING
    avant d'arriver à ORDER BY.

    Autrement dit, tu vas un peu vite dans ta réflexion !

    - Une requête qui select tous les 'people', en les triant par DATE de l''event' le plus récent qui leur soit associé, sachant qu'il peut évidemment y avoir plusieurs 'event' pour un 'people'.
    On cherche donc l'event le plus récent (qui a la date la plus grande) pour chaque people :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT p.id, p.nom, MAX(e.laDate) AS DateDernierEvent
    FROM people AS p
    INNER JOIN event AS e ON p.id = e.about_id
    GROUP BY p.id
    ORDER BY MAX(e.laDate) DESC
    Maintenant qu'on a la date de l'event le plus récent, on peut l'utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT t.nom, t.DateDernierEvent, e1.type
    FROM event AS e1
    INNER JOIN (
      SELECT p.id, p.nom, MAX(e.laDate) AS DateDernierEvent
      FROM people AS p
      INNER JOIN event AS e ON p.id = e.about_id
      GROUP BY p.id
    ) AS t ON e1.about_id = t.id
    WHERE e1.laDate = t.DateDernierEvent
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    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 !

  4. #4
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Salut !

    Attention à soit ajouter p.nom dans le GROUP BY, soit prendre max(p.nom) dans le SELECT.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 9
    Par défaut
    Merci beaucoup à vous, surtout CinePhil pour le code et l'explication ! \o/

    Je vais mettre ça en place, et étudier un peu ces MAX() et INNER JOIN que je ne connais pas (je ne connais vraiment que les trucs basiques en SQL pour l'instant ...)

    Super réponse, et rapide en plus

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 9
    Par défaut
    Ca marche bien pour le tri par date, mais j'en remet une couche pour le tri par nature d'event.

    Voilà ce que j'ai fait en me basant sur l'exemple précédemment donné :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $req  = "SELECT joint.id, joint.LastOne, logs.status ";
    $req .= "FROM suit_logs AS logs ";
    $req .= "INNER JOIN (";
    $req .= "SELECT p.id, p.nickname, jlog.status AS status, MAX(jlog.date_add) AS LastOne ";
    $req .= "FROM suit_persons AS p ";
    $req .= "INNER JOIN suit_logs AS jlog ON p.id = jlog.about_id ";
    $req .= "GROUP BY p.id";
    $req .= ") AS joint ON (logs.about_id = joint.id AND logs.date_add = joint.LastOne) ";
    $req .= "WHERE logs.date_add = joint.LastOne ORDER BY joint.status";
    Le tri par suit_logs.status fonctionne, mais se base sur le status le plus ancien attribué à une personne (ou sans doute le premier status trouvé dans la liste attribué à cette personne). Je voudrais donc qu'il se base sur le status le plus récent.

    Le "MAX(jlog.date_add)" / "logs.date_add = joint.LastOne" n'est pas censé sélectionner seulement le log le plus récent ?

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Par défaut
    Une remarque sur le code: à supposer que ce soit du php, mais ça existe aussi en Perl, la syntaxe dite "here-doc" est beaucoup plus pratique pour mettre en chaîne de caractères des requêtes multi-lignes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    $str = <<<REQUETE
    SELECT p.id, p.nom, MAX(e.laDate) AS DateDernierEvent
    FROM people AS p
    INNER JOIN event AS e ON p.id = e.about_id
    GROUP BY p.id
    ORDER BY MAX(e.laDate) DESC
    REQUETE;
    Ca permet non seulement de copier-coller directement mais aussi de pouvoir intégrer directement des guillemets et apostrophes sans avoir à les échapper.

  8. #8
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par Yatta Voir le message
    Ca marche bien pour le tri par date, mais j'en remet une couche pour le tri par nature d'event.

    Voilà ce que j'ai fait en me basant sur l'exemple précédemment donné :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $req  = "SELECT joint.id, joint.LastOne, logs.status ";
    $req .= "FROM suit_logs AS logs ";
    $req .= "INNER JOIN (";
    $req .= "SELECT p.id, p.nickname, jlog.status AS status, MAX(jlog.date_add) AS LastOne ";
    $req .= "FROM suit_persons AS p ";
    $req .= "INNER JOIN suit_logs AS jlog ON p.id = jlog.about_id ";
    $req .= "GROUP BY p.id";
    $req .= ") AS joint ON (logs.about_id = joint.id AND logs.date_add = joint.LastOne) ";
    $req .= "WHERE logs.date_add = joint.LastOne ORDER BY joint.status";
    Le tri par suit_logs.status fonctionne, mais se base sur le status le plus ancien attribué à une personne (ou sans doute le premier status trouvé dans la liste attribué à cette personne). Je voudrais donc qu'il se base sur le status le plus récent.

    Le "MAX(jlog.date_add)" / "logs.date_add = joint.LastOne" n'est pas censé sélectionner seulement le log le plus récent ?
    La sous-requête ne peut pas fonctionner correctement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      SELECT p.id, p.nickname, jlog.status AS status, MAX(jlog.date_add) AS LastOne
      FROM suit_persons AS p
      INNER JOIN suit_logs AS jlog ON p.id = jlog.about_id
      GROUP BY p.id
    Comme l'a signalé PACMAN, dans le GROUP BY doivent figurer toutes les colonnes qui ne font pas l'objet d'une fonction de regroupement (MAX, MIN, AVG, COUNT, SUM).
    Avec ma requête, GROUP BY p.id était suffisant parce que p.nom est directement dépendant de p.id mais dans la tienne, jlog.status donnera la première valeur trouvée pour cette colonne et ce ne sera pas forcément celle que tu cherches à avoir.
    A noter que MySQL est tolérant sur l'absence de colonnes dans le GROUP BY mais que d'autres SGBD le refuseraient carrément !

    Si je comprends bien ta requête et que je la rapporche de ton besoin, jlog.status correspondrait à mon e1.type ?
    Alors ta requête est inutilement compliquée ! Il suffit de transformer ma requête et de faire le tri sur la bonne colonne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT joint.id, joint.lastone, logs.status
    FROM suit_logs AS logs
    INNER JOIN (
      SELECT p.id, p.nickname, MAX(jlog.date_add) AS LastOne
      FROM suit_persons AS p
      INNER JOIN suit_logs AS jlog ON p.id = jlog.about_id
      GROUP BY p.id, p.nickname
    ) AS joint ON logs.date_add = joint.LastOne
    ORDER BY logs.status
    Nota :
    Comme tu le vois dans le code ci-dessus, STATUS est uin mot réservé du SQL et ne devrait pas être utilisé pour nommer une colonne.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    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 !

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 18/01/2010, 11h29
  2. Réponses: 5
    Dernier message: 10/12/2007, 15h24
  3. Réponses: 2
    Dernier message: 22/03/2007, 16h19
  4. Réponses: 6
    Dernier message: 27/08/2006, 18h57
  5. Selection d'une valeur dans une autre table
    Par beurnoir dans le forum Access
    Réponses: 1
    Dernier message: 13/10/2005, 12h02

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