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 :

Aide pour requête qui parait simple [MySQL-5.7]


Sujet :

Requêtes MySQL

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Technicien réseau
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseau
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 8
    Points
    8
    Par défaut Aide pour requête qui parait simple
    Bonjour à tous,
    J'essaye de mettre en place une requête qui parait simple et complexe à la fois.
    Ça fait 2 jours que je cherche et que je tente des choses (select distinct, limit, etc.) mais sans résultat
    Je vois comment le faire avec une boucle php mais j'aurai préféré utiliser la puissance du sql

    J'ai une table qui ressemble à ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    table mouv
    idmouv	   idterr              datedebut	 datefin
    1		5		1/1/2020	1/2/2020
    2		15		2/1/2020	3/1/2020
    3		3		3/1/2020	1/4/2020
    4		5		1/3/2020	1/5/2020
    5		3		1/5/2020	1/7/2020
    6		5	       1/10/2020        NULL
     
    Resultat souhaité:
    idmouv	   idterr              datedebut	 datefin
    2		15		2/1/2020	3/1/2020
    5		3		1/5/2020	1/7/2020
    La mission est de recuperer une seule itération de idterr (la plus récente selon datefin) sauf si le idterr a une datefin NULL.

    Si quelqu'un à une solution a me proposer
    Merci pour votre aide.

  2. #2
    Membre averti
    Profil pro
    Administrateur
    Inscrit en
    Mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2008
    Messages : 237
    Points : 433
    Points
    433
    Par défaut
    Les deux plus récents idterr

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT idmouv, idterr, datedebut, datefin
    FROM mouv
    WHERE datefin IS NOT NULL
    ORDER BY datefin DESC
    LIMIT 2
    Cela ne marchera que si datefin est de type date
    Votre format de date n'est pas approprié, quel est le type de vos colonnes datefin et datedebut ?
    Mettez les colonnes datefin et datedebut au format date si ce n'est pas le cas

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Technicien réseau
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseau
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    Merci pour votre proposition de requête !

    datefin et datedebut est bien de type date.
    Je désire obtenir toute les résultats de la table, pas les 2 premières réponses. Je peux donc retirer le 'limit 2' de la requête.

    Par contre, si je précise seulement 'WHERE datefin IS NOT NULL' je me retrouve avec les idmouv de 1 a 5.
    Comme l'idmouv 6 a une datefin NULL, je ne desire aucun idmouv ou l'on retrouve idterr=5
    Et je souhaite avoir uniquement un idmouv par idterr, le plus récent et qui ne soit pas null.

    Pour aider, voici une formule qui marche mais avec une boucle en php.
    Le problème c'est qu'avec 200 idterr, ca génère 200 requêtes !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for ($num  = 1;$num<$nummax ; $num ++) {
      "SELECT * from mouv where datefin is not NULL and idterr=$num order by datefin DESC limit 1";
    }
    Es espérant avoir été plus clair.
    C'est pour cela que je précisait que ça paraissait simple a première vue

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 561
    Points
    38 561
    Billets dans le blog
    9
    Par défaut
    Bonjour,

    Il y a plein de réponses possibles pour ce besoin.
    Consultez mon blog ICI

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Technicien réseau
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseau
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par escartefigue Voir le message
    Bonjour,

    Il y a plein de réponses possibles pour ce besoin.
    Consultez mon blog ICI
    Merci beaucoup pour cette réponse.
    Mais malheureusement, je n'utilise qu'une seule table. J'ai essayé de l'adapter avec les 2 premières méthodes du blog mais sans succès

    Entre temps, ca ma donné des idées, j'ai tenté ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        SELECT *,max(datefin) as datemax
        FROM mouv
        WHERE datefin is not null
        group by idterr
        order by datemax
    Ca marche presque mais il m'affiche quand meme certains idterr quand datefin est null et à cause du group by, je ne peux pas recuperer les parametres de la bonne ligne

  6. #6
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 561
    Points
    38 561
    Billets dans le blog
    9
    Par défaut
    Bonjour

    Qui peut le plus peut le moins, j'ai mis des exemples avec jointure dans mon blog, s'il n'y a qu'une seule table, c'est encore plus simple

    Pour le reste. Faire un select * est de base une erreur (instabilité du résultat, performances dégradées) mais encore plus avec un regroupement !
    Seul MySQL accepte une syntaxe aussi aberrante et fournit en ce cas un résultat aléatoire (et il ne saurait en être autrement)

    Mettez en cohérence les colonnes du group by et du select :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        SELECT idterr
             , max(datefin) as datemax
        FROM mouv
        WHERE datefin is not null
        group by idterr
        order by datemax
    Pour filtrer le résultat d'un regroupement, il faut utiliser HAVING.
    Sinon, vous pouvez aussi utiliser COALESCE pour remplacer les "null" par une valeur fixe

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Technicien réseau
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseau
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    Je ne savais pas !
    Merci pour ce retour expérience.

    J'ai donc corrigé et adapté la requête avec HAVING

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        SELECT idterr,datefin,idmouv,max(datefin) as datemax FROM mouv
        WHERE datefin is not null
    	group by idterr having datefin=datemax
    	order by idterr
    Le résultat est un peu meilleur mais je n'ai toujours pas le résultat espéré.
    J'ai regardé COALESCE mais je ne vois pas comment ça peux m'aider et remplacer les null.
    Je galère

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Technicien réseau
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseau
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    Je pense savoir pourquoi ça ne marche pas
    mais je ne vois pas comment codé ce mécanisme.

    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
    table mouv
    idmouv	   idterr              datedebut	 datefin
    1		5		1/1/2020	1/2/2020
    4		5		1/3/2020	1/5/2020
    6		5	       1/10/2020        NULL
     
    Si pour un idterr, j ai un null en datefin, je ne veux aucun resultat
     
    table mouv
    idmouv	   idterr              datedebut	 datefin
    3		3		3/1/2020	1/4/2020
    5		3		1/5/2020	1/7/2020
     
    Si plusieurs idterr, je desire le dernier:
    idmouv	   idterr              datedebut	 datefin
    5		3		1/5/2020	1/7/2020

  9. #9
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 561
    Points
    38 561
    Billets dans le blog
    9
    Par défaut
    OK

    Si pour un idterr, j ai un null en datefin, je ne veux aucun resultat
    Du coup il suffit d'utilser NOT EXISTS :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select idterr, max(datefin)
    from mouv T1
    where not exists
         (select 1
          from mouv T2
          where T2.idterr=T1.idterr
            and T2.datefin is null)
    group by idterr

  10. #10
    Membre averti
    Profil pro
    Administrateur
    Inscrit en
    Mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2008
    Messages : 237
    Points : 433
    Points
    433
    Par défaut
    Citation Envoyé par Blamp1 Voir le message
    Merci pour votre proposition de requête !

    datefin et datedebut est bien de type date.

    Comme l'idmouv 6 a une datefin NULL, je ne desire aucun idmouv ou l'on retrouve idterr=5

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for ($num  = 1;$num<$nummax ; $num ++) {
      "SELECT * from mouv where datefin is not NULL and idterr=$num order by datefin DESC limit 1";
    }
    Je n'avais pas bien compris votre requête.
    Mais déjà, pourquoi avez-vous des champs datefin à null, Votre table est-elle bien modélisée ?

    Plusieurs approches possibles
    Exclure les idterr dont datefin a été null

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT max(idmouv) as idmouv, idterr, max(datedebut) as datedebut, max(datefin) as datefin
    FROM mouv
    WHERE idterr not IN (SELECT idterr FROM mouv WHERE datefin is null)
    GROUP BY idterr
    ORDER BY datefin;

  11. #11
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 561
    Points
    38 561
    Billets dans le blog
    9
    Par défaut
    @manzeki : attention, il est préférable pour ce besoin d'utiliser not exists comme je l'ai proposé plus haut que not in.
    En effet, (not) in construit l'ensemble complet des résultats satisfaisant le prédicat, alors que (not) exists ne vérifie la présence que d'une seule occurrence.
    Selon la qualité de l'optimiseur et le temps dont il dispose le résultat est parfois identique, mais pas toujours. C'est pourquoi (not) exists est préférable

  12. #12
    Futur Membre du Club
    Homme Profil pro
    Technicien réseau
    Inscrit en
    Décembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseau
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    Merci Manzeki et escarfigue
    Vos conseils précieux m'ont appris beaucoup de chose et ont élargis mon champ de vision du SQL.

    Voici ma requête finale qui fait exactement ce que je voulais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     select idterr,datefin,idmouv,max(datefin) as datemax
    from mouvement T1
    where not exists
         (select 1
          from mouvement T2
          where T2.idterr=T1.idterr
            and T2.datefin is null)
    group by idterr
    order by datemax
    Je ne suis pas sur de pouvoir refaire tout seul ce genre de requête avec une sous requête mais je vois déjà le principe.
    Encore merci

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 12/03/2015, 06h23
  2. J'ai besoin de votre aide pour une requête
    Par ovdz dans le forum Langage SQL
    Réponses: 6
    Dernier message: 20/05/2005, 11h42
  3. Demande d'aide pour une requête
    Par arkzor dans le forum Requêtes
    Réponses: 3
    Dernier message: 28/12/2004, 02h40
  4. Besoin d'aide pour une Requête SQL ...
    Par Kokito dans le forum Requêtes
    Réponses: 2
    Dernier message: 07/07/2004, 11h56
  5. besoin d'aide pour une requête
    Par Damien69 dans le forum Langage SQL
    Réponses: 11
    Dernier message: 31/03/2004, 15h38

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