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 :

Retourner des enregistrements dont un champ à la plus grande valeur connue en table [MySQL-5.5]


Sujet :

Requêtes MySQL

  1. #1
    Nouveau membre du Club
    Inscrit en
    Octobre 2008
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 22
    Points : 28
    Points
    28
    Par défaut Retourner des enregistrements dont un champ à la plus grande valeur connue en table
    Bonjour,

    J'ai une table comprenant un N° de client, un N° de facture, une date de facture ainsi qu'un etat de facture.

    Facture:

    Id_Client Num_Fact Date_Fact Etat
    1 1 20150101 A
    1 2 20150202 B
    1 3 20150303 C
    1 4 20150404 B
    2 1 20150110 A
    2 2 20150211 B
    2 3 20150515 C
    2 4 20150404 B

    Connaitre pour chaque client la date de sa facture la plus récente est facile:

    select Id_Client, MAX(Date_Fact)
    from facture
    group by Id_Client;

    1 20150404
    2 20150515

    Mais là ou je coince c'est lorsque je veux remonter aussi le N° de facture et son état.

    autrement dit je souhaiterais que ma requête me remonte ceci:

    Id_Client Num_Fact Date_Fact Etat
    1 4 20150404 B
    2 3 20150515 C

    Bien entendu j'ai testé la requête suivante et celle ci ne fonctionne pas:

    select Id_Client, Num_Fact, MAX(Date_Fact), Etat
    from facture
    group by Id_Client;


    Est ce possible en une seule requête, sans utiliser une vue ou une table temporaire.

    Merci d'avance.

  2. #2
    Membre confirmé Avatar de Diablo_22
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2005
    Messages
    498
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2005
    Messages : 498
    Points : 490
    Points
    490
    Par défaut
    Bonjour,

    quand tu exécute ta requête, quel est l'erreur généré ?
    N'oubliez pas la balise

    est ton ami mais quand Google ne trouve pas quelque choses, il demande à Chuck Norris.

  3. #3
    Nouveau membre du Club
    Inscrit en
    Octobre 2008
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 22
    Points : 28
    Points
    28
    Par défaut
    Il n'y a pas d'erreur de syntaxe, c'est juste que le résultat remonté est faux (l’état et le N° de facture ne corresponde pas à l’enregistrement portant la plus grande date)

  4. #4
    Membre confirmé Avatar de Diablo_22
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2005
    Messages
    498
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2005
    Messages : 498
    Points : 490
    Points
    490
    Par défaut
    Essaye ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT f.*
    FROM facture f
    INNER JOIN
    (
    SELECT Id_Client, Num_Fact, MAX(Date_Fact) AS maxDate, Etat
    FROM facture 
    GROUP BY Id_Client
    ) groupef ON f.Id_Client= groupef.Id_ClientAND f.Date_Fact = groupef.maxDate
    N'oubliez pas la balise

    est ton ami mais quand Google ne trouve pas quelque choses, il demande à Chuck Norris.

  5. #5
    Nouveau membre du Club
    Inscrit en
    Octobre 2008
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 22
    Points : 28
    Points
    28
    Par défaut
    C'est bon ca fonctionne.
    Merci beaucoup.

    J'ai juste honte de ne pas y avoir pensé ...

    Pour info, j'ai adapté un peu la requête (je pense que tu t'es fait piéger par le copier-coller) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT f.*
    FROM facture f
    INNER JOIN
    (
    SELECT Id_Client, MAX(Date_Fact) AS maxDate
    FROM facture 
    GROUP BY Id_Client
    ) groupef ON f.Id_Client= groupef.Id_ClientAND f.Date_Fact = groupef.maxDate

  6. #6
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut à tous.

    Je trouve que cette solution est bien compliquée, juste pour récupérer la ligne ayant la plus grande date pour un client donné.
    Voici une autre solution sans jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    select *
    from (select * from facture order by id_client, date_fact desc) as x
    group by id_client
    --------------
     
    +-----------+----------+------------+------+
    | id_client | num_fact | date_fact  | etat |
    +-----------+----------+------------+------+
    |         1 |        4 | 2015-04-04 | B    |
    |         2 |        3 | 2015-05-15 | C    |
    +-----------+----------+------------+------+
    Sinon, pour récupérer une ligne en particulier, à partir de sa valeur, il suffit d'utiliser un subselect comme ci-après :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    select *
    from facture as tb1
    where date_fact = (
            select max(date_fact)
            from facture as tb2
            where tb2.id_client = tb1.id_client
            group by id_client
            )
    --------------
     
    +-----------+----------+------------+------+
    | id_client | num_fact | date_fact  | etat |
    +-----------+----------+------------+------+
    |         1 |        4 | 2015-04-04 | B    |
    |         2 |        3 | 2015-05-15 | C    |
    +-----------+----------+------------+------+
    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  7. #7
    Nouveau membre du Club
    Inscrit en
    Octobre 2008
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 22
    Points : 28
    Points
    28
    Par défaut
    Salut,

    Merci de ta réponse Artemus24 , mais ce qui me dérange c'est l'utilisation du Group By sans fonction. Il est vrai que j'ai lu ceci http://sql.developpez.com "La manière simple de comprendre le GROUP BY c’est tout simplement d’assimiler qu’il va éviter de présenter plusieurs fois les mêmes lignes. C’est une méthode pour éviter les doublons." mais ta solution pose en plus l'assertion que dans ce cas, c'est la première ligne qui sera remontée. Si c'est dans la norme, c'est bien vu, si c'est pas le cas ....

    Sinon ta deuxième requete, sans le group by, me va tout à fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    select *
    from facture as tb1
    where date_fact = (
            select max(date_fact)
            from facture as tb2
            where tb2.id_client = tb1.id_client
            )
    A+

  8. #8
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Almindra.

    Citation Envoyé par Almindra
    ce qui me dérange c'est l'utilisation du Group By sans fonction.
    Quelle fonction ? Dans cette exemple, il n'y en a pas.
    Qu'est-ce qui te dérange dans le fait que je n'utilise pas de fonction ?

    Citation Envoyé par Almindra
    La manière simple de comprendre le GROUP BY c’est tout simplement d’assimiler qu’il va éviter de présenter plusieurs fois les mêmes lignes.
    Un 'group by' comme son nom l'indique sert à faire un regroupement (grouper par).

    Citation Envoyé par Almindra
    C’est une méthode pour éviter les doublons.
    Si tu as plusieurs lignes qui ont le même critère (le cas des doublons), le SGBDR va devoir en sélectionner une. Il choisit de sélectionner la première qui se présente.
    Donc oui, cela sert, non pas à éviter des doublons, mais à les regrouper.

    Citation Envoyé par Almindra
    mais ta solution pose en plus l'assertion que dans ce cas, c'est la première ligne qui sera remontée
    Il faut comprendre que la première ligne va servir d'initialisation à des opérations que tu vas effectuer dessus.
    Donc si je fais un sum() sur une colonne contenant des montants, le résultats sera le total de tous ces doublons.
    Mais si je ne fais rien, par cette astuce, je supprime toutes les autres lignes (les doublons).

    Citation Envoyé par Almindra
    Si c'est dans la norme, c'est bien vu, si c'est pas le cas ....
    Qu'est-ce que la norme vient faire ici ? On te donne un outil. A toi de savoir t'en servir correctement.

    Tu vas vite t'apercevoir que l'on utilise des astuces pour gagner du temps. Le critère le plus important est la performance !
    Si tu as deux solutions et que l'une met une heure pour s'exécuter et l'autre trente secondes, laquelle choisis-tu ?

    Si je ne respectais pas la norme comme tu dis, le SGBDR me l'indiquerait tout de suite par une anomalie.
    Et de toute façon, le résultat sera moins performant. Donc la question ne se pose pas.

    Citation Envoyé par Almindra
    Sinon ta deuxième requete, sans le group by, me va tout à fait
    Si tu fais un 'explain' sur ces deux solutions, tu vas remarquer que la seconde solution est plus performance que la première.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 11/07/2006, 16h13
  2. [MySQL 4.0.24] Compter des dossiers dont un champ est vide
    Par boniface dans le forum Langage SQL
    Réponses: 2
    Dernier message: 30/06/2006, 14h29
  3. Retourné des lignes dont certains champs sont vides
    Par griese dans le forum Langage SQL
    Réponses: 5
    Dernier message: 27/06/2006, 10h23
  4. Réponses: 4
    Dernier message: 27/04/2006, 09h22
  5. somme des enregistrement d'un champ
    Par rostomides dans le forum Bases de données
    Réponses: 5
    Dernier message: 07/04/2006, 19h09

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