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 :

Besoin d'aide pour requête SQL


Sujet :

Langage SQL

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    306
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 306
    Points : 194
    Points
    194
    Par défaut Besoin d'aide pour requête SQL
    Bonjour à tous,

    J'ai besoin de votre aide pour construire et optimiser une requête SQL.

    Je vous explique : j'ai une table qui liste des articles et une autre qui contient l'historique de changement de statut de mes articles.
    J'ai besoin en une seule requête de récupérer la liste des articles avec pour chacun d'entre eux son dernier statut et la date de son dernier statut.

    Je vous ai modelisé les tables pour faciliter la compréhension :



    J'ai d'abord pensé à faire une requête du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT art_nom, max(sta_date), sta_code
    FROM article A INNER JOIN statut S ON A.art_id = S.art_id
    mais le code statut retourné n'est pas forcément celui correspondant à la max(sta_date).

    Est-ce que quelqu'un aurait une idée ?
    Merci d'avance.

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Italie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 271
    Points : 491
    Points
    491
    Par défaut
    Moi je pensais a cette solution
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT art_nom, sta_date, sta_code
    FROM 
    (
    SELECT art_id, max(sta_date) Last_Modif
    FROM statut
    GROUP BY art_id
    ) B
    INNER JOIN statut  C ON (B.art_id=C.art_id and sta_date=Last_Modif)
    INNER JOIN article D ON (B.art_id=D.art_id)

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    306
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 306
    Points : 194
    Points
    194
    Par défaut
    Bonjour fab256,

    Merci pour ta réponse.

    Penses-tu que c'est la seule solution car j'ai un peu peur des performances... en sachant que pour un article, je peux avoir jusqu'à 10 statuts d'historique ?

  4. #4
    Membre habitué Avatar de tfc3146
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Février 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur décisionnel
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Février 2009
    Messages : 79
    Points : 150
    Points
    150
    Par défaut
    Bonjour,

    Essaye cela peut-être (non testé), je ne sais pas si les temps de réponses sont mieux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT A.art_nom, S.sta_code, S.sta_date
    FROM ARTICLE A
    JOIN STATUT S ON A.art_id=S.art_id
    WHERE sta_date = (SELECT MAX(sta_date)
                               FROM STATUT S2
                               WHERE S2.art_id=S.art_id)
    C'est en faisant n'importe quoi qu'on devient n'importe qui
    Si un message vous a aidé, n'hésitez pas à mettre +1

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Italie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 271
    Points : 491
    Points
    491
    Par défaut
    Effectivement la requette de tfc3146 est beaucoup plus performante , j'ai fait un petit test sur l'exemple cité plus haut ca prends 0.0011 sec alors que la solution que j'ai proposé prends 0.0393 sec.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    306
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 306
    Points : 194
    Points
    194
    Par défaut
    Je vous remercie pour vos réponses.
    Je vais donc opter pour la solution de tfc3146.

    Si jamais une autre personne trouve encore mieux, je suis preneur.

    Merci encore.

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    306
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 306
    Points : 194
    Points
    194
    Par défaut
    Bonjour,

    Je relance ce post car je rencontre un problème lorsque les deux derniers statuts de mon article ont la même date.
    Dans ce cas là, la requête de tfc3146 me renvoie deux lignes de résultats pour un même article.

    Est-ce qu'il y a moyen de modifier la requête pour ne récupérer, pour un article, que le statut ayant la max(date) et dont l'id du statut (sta_id) est le plus élevé ? cela me permettrait de n'avoir qu'un statut par article et donc qu'une ligne par article...

    Merci à vous.

  8. #8
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    bonjour,

    lisez ceci : http://sqlpro.developpez.com/cours/sqlaz/ensembles/
    En particulier la partie sur le group by

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    306
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 306
    Points : 194
    Points
    194
    Par défaut
    Bonjour,

    Merci de votre réponse.

    J'ai effectivement pensé à utiliser un group by mais dans ce cas-là je ne vois vraiment pas dans quelle mesure il peut m'être utile.

  10. #10
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    oui effectivement j’ai peut être un peu lu trop vite la demande.

    Que lest votre sgbd ?

    Ensuite est-ce que vouloir la ligne avec l'id max est pertinent (c'est une pk donc ..) ? Fonctionnellement ceci vous convient ?

    edit: surtout au vu de votre exemple, pour un même article :
    sta_id : 7, date : 12-02-2011
    sta_id : 8, date : 11-02-2011

    donc prendre le statut avec le sta_id le plus élevé correspond-il vraiment au résultat voulu ?

  11. #11
    Membre habitué Avatar de tfc3146
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Février 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur décisionnel
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Février 2009
    Messages : 79
    Points : 150
    Points
    150
    Par défaut
    Et quelque chose du genre ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT A.art_nom, S.sta_code,S.sta_id
    FROM ARTICLE A
    JOIN STATUT S ON A.art_id=S.art_id
    WHERE S.sta_date=(SELECT MAX(S2.sta_date)
                      FROM STATUT S2
                      WHERE S2.art_id=S.art_id)
    GROUP BY A.art_nom,S.sta_code
    HAVING S.sta_id = (SELECT MAX(S3.sta_id)
    		   WHERE s3.art_id=S.art_id
    		   AND s3.sta_date=s2.sta_date)
    C'est en faisant n'importe quoi qu'on devient n'importe qui
    Si un message vous a aidé, n'hésitez pas à mettre +1

  12. #12
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Italie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 271
    Points : 491
    Points
    491
    Par défaut
    Une petite modification sur la requete que j'avais proposé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT art_nom, sta_date, sta_code
    FROM 
    (
    SELECT art_id, max(sta_date) Last_Modif, max(sta_id) Last_Id
    FROM statut
    GROUP BY art_id
    ) B
    INNER JOIN statut  C ON (B.art_id=C.art_id and sta_date=Last_Modif and sta_id=Last_Id)
    INNER JOIN article D ON (B.art_id=D.art_id)

  13. #13
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Citation Envoyé par fab256 Voir le message
    Une petite modification sur la requete que j'avais proposé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT art_nom, sta_date, sta_code
    FROM 
    (
    SELECT art_id, max(sta_date) Last_Modif, max(sta_id) Last_Id
    FROM statut
    GROUP BY art_id
    ) B
    INNER JOIN statut  C ON (B.art_id=C.art_id and sta_date=Last_Modif and sta_id=Last_Id)
    INNER JOIN article D ON (B.art_id=D.art_id)
    bonjour,

    cette requête ne marchera pas.

    le sta_id le plus élevé pour un article n'est pas forcément celui qui à la date la plus grande.

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    306
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 306
    Points : 194
    Points
    194
    Par défaut
    Bonjour,

    Merci pour vos réponses.

    @punkoff : je suis sous MySQL

    @punkoff : fonctionnellement, c'est effectivement ce que je souhaite à savoir dans le cas où un article possède ses deux derniers statuts à la même date, prendre le statut qui a été inséré en dernier donc avec le sta_id le plus grand.

    @tfc3146 : merci, je vais partir sur ta solution. J'ai quand même peur de perfs étant donné que cela oblige à faire une sous-requête supplémentaire... mais si j'ai pas le choix....

    Merci encore.

  15. #15
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    la seule solution sans sous-requete serai d'avoir les fonctions de fenêtrage.

    Mais c'est foutu pour MySql de ce côté là.


    et est-ce que quelque-chose dans ce genre là fonctionne ? (éviterai une 2eme sous-requete )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    select art_nom, sta_code, sta_date
    from article art
    inner join statut sta1 on sta1.art_id = art.art_id
    where sta1.sta_id = (select sta2.sta_id
    				from statut sta2
    				where sta2.art_id = sta1.art_id
    				order by sta2.sta_date desc, sta2.sta_id desc
    				TOP 1);

  16. #16
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    306
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 306
    Points : 194
    Points
    194
    Par défaut
    @punkoff : je viens de tester et ta requête fonctionne bien.

    Entre ces deux requêtes, laquelle est la plus performante ?

  17. #17
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    je ne saurai répondre, il faudrai regarder les plans d'execution et les comparer (je n'ai pas mySql d'installé)

    Niveau indexation pour la 2eme requête ça serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    create index idx_test on statut (art_id, sta_date desc, sta_id desc)
    Et pareil comparez les plans avant et après le test de cet index.

  18. #18
    Membre habitué Avatar de tfc3146
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Février 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur décisionnel
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Février 2009
    Messages : 79
    Points : 150
    Points
    150
    Par défaut
    ORDER BY c'est lourd. Peut-être que si ta table n'est pas très grosse, tu ne verras pas senseiblement la différence en tant de réponse, mais là l'ORDER BY ne s'impose pas => il vaut mieux utiliser MAX.
    C'est en faisant n'importe quoi qu'on devient n'importe qui
    Si un message vous a aidé, n'hésitez pas à mettre +1

  19. #19
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Citation Envoyé par tfc3146 Voir le message
    ORDER BY c'est lourd. Peut-être que si ta table n'est pas très grosse, tu ne verras pas senseiblement la différence en tant de réponse, mais là l'ORDER BY ne s'impose pas => il vaut mieux utiliser MAX.
    Même avec l'index déjà trié ..?

  20. #20
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Essayez aussi ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT A.art_nom, S1.sta_code, S1.sta_date
      FROM ARTICLE A
           INNER JOIN STATUT S1
             ON S1.art_id = A.art_id
           INNER JOIN ( select max(S3.STA_ID) as STA_ID_MAX
                          FROM STATUT S3
                               INNER JOIN ( select ART_ID, MAX(STA_DATE) as STA_DATE_MAX
                                              FROM STATUT
                                          group by art_id) S4
                                ON S4.art_id       = S3.art_id
                               AND S4.STA_DATE_MAX = S3.STA_DATE
                      group by ART_ID) S2
             ON S2.STA_ID_MAX = S1.STA_ID
    C'est vraiment moche le SQL chez MySQL !

Discussions similaires

  1. [SQL Server 2005] Besoin d'aide pour requête
    Par Definol dans le forum Langage SQL
    Réponses: 5
    Dernier message: 18/07/2007, 13h55
  2. Besoin d'aide pour requête SQL
    Par dinver78 dans le forum Langage SQL
    Réponses: 1
    Dernier message: 21/05/2007, 18h20
  3. Besoin d'aide pour requête SQL
    Par vallica dans le forum Requêtes
    Réponses: 10
    Dernier message: 08/06/2006, 23h16
  4. Besoin d'aide pour requête sur grosse table
    Par Fabouney dans le forum Langage SQL
    Réponses: 3
    Dernier message: 25/01/2006, 09h01

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