Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 03/06/2011, 22h53   #1
Membre habitué
 
Inscription : juin 2004
Messages : 296
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : juin 2004
Messages : 296
Points : 147
Points : 147
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 :
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.
__________________
- Blog
- stages-aikido.fr
kaboume est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/06/2011, 01h11   #2
Membre confirmé
 
Homme
Développeur informatique
Inscription : avril 2011
Messages : 196
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Italie

Informations professionnelles :
Activité : Développeur informatique
Secteur : Transports

Informations forums :
Inscription : avril 2011
Messages : 196
Points : 298
Points : 298
Moi je pensais a cette solution
Code :
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)
fab256 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 04/06/2011, 09h58   #3
Membre habitué
 
Inscription : juin 2004
Messages : 296
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : juin 2004
Messages : 296
Points : 147
Points : 147
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 ?
__________________
- Blog
- stages-aikido.fr
kaboume est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/06/2011, 10h37   #4
Membre habitué
 
Avatar de tfc3146
 
Homme Robert Labrousse
Développeur décisionnel
Inscription : février 2009
Messages : 79
Détails du profil
Informations personnelles :
Nom : Homme Robert Labrousse
Localisation : France

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

Informations forums :
Inscription : février 2009
Messages : 79
Points : 134
Points : 134
Bonjour,

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

Code :
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)
tfc3146 est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 04/06/2011, 11h10   #5
Membre confirmé
 
Homme
Développeur informatique
Inscription : avril 2011
Messages : 196
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Italie

Informations professionnelles :
Activité : Développeur informatique
Secteur : Transports

Informations forums :
Inscription : avril 2011
Messages : 196
Points : 298
Points : 298
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.
fab256 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/06/2011, 11h54   #6
Membre habitué
 
Inscription : juin 2004
Messages : 296
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : juin 2004
Messages : 296
Points : 147
Points : 147
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.
__________________
- Blog
- stages-aikido.fr
kaboume est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 08h10   #7
Membre habitué
 
Inscription : juin 2004
Messages : 296
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : juin 2004
Messages : 296
Points : 147
Points : 147
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.
__________________
- Blog
- stages-aikido.fr
kaboume est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 08h53   #8
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
bonjour,

lisez ceci : http://sqlpro.developpez.com/cours/sqlaz/ensembles/
En particulier la partie sur le group by
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 08h58   #9
Membre habitué
 
Inscription : juin 2004
Messages : 296
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : juin 2004
Messages : 296
Points : 147
Points : 147
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.
__________________
- Blog
- stages-aikido.fr
kaboume est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 09h08   #10
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
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 ?
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 09h24   #11
Membre habitué
 
Avatar de tfc3146
 
Homme Robert Labrousse
Développeur décisionnel
Inscription : février 2009
Messages : 79
Détails du profil
Informations personnelles :
Nom : Homme Robert Labrousse
Localisation : France

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

Informations forums :
Inscription : février 2009
Messages : 79
Points : 134
Points : 134
Et quelque chose du genre ?

Code :
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)
__________________
Citation:
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
tfc3146 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 23/06/2011, 09h43   #12
Membre confirmé
 
Homme
Développeur informatique
Inscription : avril 2011
Messages : 196
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Italie

Informations professionnelles :
Activité : Développeur informatique
Secteur : Transports

Informations forums :
Inscription : avril 2011
Messages : 196
Points : 298
Points : 298
Une petite modification sur la requete que j'avais proposé
Code :
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)
fab256 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 09h56   #13
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
Citation:
Envoyé par fab256 Voir le message
Une petite modification sur la requete que j'avais proposé
Code :
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.
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 13h14   #14
Membre habitué
 
Inscription : juin 2004
Messages : 296
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : juin 2004
Messages : 296
Points : 147
Points : 147
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.
__________________
- Blog
- stages-aikido.fr
kaboume est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 13h33   #15
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
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 :
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);
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 13h43   #16
Membre habitué
 
Inscription : juin 2004
Messages : 296
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : juin 2004
Messages : 296
Points : 147
Points : 147
@punkoff : je viens de tester et ta requête fonctionne bien.

Entre ces deux requêtes, laquelle est la plus performante ?
__________________
- Blog
- stages-aikido.fr
kaboume est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 13h46   #17
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
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 :
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.
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 14h10   #18
Membre habitué
 
Avatar de tfc3146
 
Homme Robert Labrousse
Développeur décisionnel
Inscription : février 2009
Messages : 79
Détails du profil
Informations personnelles :
Nom : Homme Robert Labrousse
Localisation : France

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

Informations forums :
Inscription : février 2009
Messages : 79
Points : 134
Points : 134
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.
__________________
Citation:
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
tfc3146 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 14h17   #19
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
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é ..?
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2011, 16h50   #20
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 433
Points : 10 433
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Essayez aussi ainsi :
Code :
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 !
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 18h38.


 
 
 
 
Partenaires

Hébergement Web