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 :

Recherche d'un attribut maximum dans une liste d'article minimum


Sujet :

Langage SQL

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 5
    Points : 3
    Points
    3
    Par défaut Recherche d'un attribut maximum dans une liste d'article minimum
    Bonjour,

    Etant débutant en SQL, je me retrouve devant un problème

    J'ai un champs A, pour ce champs A, j'ai plusieurs articles dans un champs B, puis de ce champs B, j'ai plusieurs articles dans un champs C qui ont tous une date correspondante dans un champs D, par exemple :

    Champs A Champs B Champs C Champs D
    nom1 1 N 01/01/2000
    nom1 3 N 01/01/2000
    nom1 3 Y 31/12/1999
    nom1 5 Y 01/01/2000
    nom1 5 N 31/12/1999
    nom1 7 Y 01/01/2010
    nom1 7 N 31/12/2000
    nom2 1 Y 01/01/2000
    nom2 1 N 01/01/2000


    Le but est que pour chaque champs A différent, je recherche à avoir le champs B minimum dont son champs C correspondant est égal à "Y"(yes) à la date la plus élevé de ce même champsB minimum

    Voici le résultat que l'on devrait obtenir :
    Champs A Champs B Champs C Champs D
    nom1 5 Y 01/01/2000
    nom2 1 Y 01/01/2000

    Ici, le couplet (nom1, 1) est éliminé car le champs n'est égal à "Y"
    Ensuite le couplet suivant (nom1, 3) est éliminé car à la date la plus élevé nous avons la valeur "N" dans le champs C


    Pour l'instant, je n'arrive pas à trouver la bonne requête, celle qui s'en rapproche le plus pour l'instant est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select a.champsA, min(a.champsB) from table a 
    where a.champsD = (select max(b.champsD) from table b where a.champsA = b.champsA AND a.champsB = b.champsB and a.champsC = 'A')
    GROUP BY a.champsA, a.champsB
    J'obtiens ceci :
    Champs A Champs B Champs C Champs D
    nom1 7 Y 01/01/2010
    nom2 1 Y 01/01/2000

    Ce qui est normal au vu de la requête, le soucis de cette requête est qu'elle ne vérifie pas que la condition sur la date la plus élevé sur le champsB minimum, je ne voie pas trop comment faire, je tourne en rond.

    Si quelqu'un peut m'aider, je le remercierai beaucoup, merci d'avance

  2. #2
    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,

    C'est quoi votre sqgb ?

    Regardez les fonction de fenêtrage si elles sont supportées par votre sgb.

    En gros ca devrait donner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    with tmp as (
    select ChampA, ChampB, ChampD, row_number() over(partition by ChampA order by ChampD desc, ChampB) as rnk
    from ma_table
    where ChampC = 'Y')
     
    select * 
    from tmp
    where rnk = 1

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Merci pour votre aide mais il y a le même problème que j'ai rencontré. La requête renvoie la date maximale pour le champsA juste et non pour le ChampsA avec le champsB minimum où il y a le ChampsC à 'Y', avez-vous une autre idée?

    J'utilise SQL Developer sous Oracle 9.1

  4. #4
    Membre du Club
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Août 2010
    Messages : 44
    Points : 69
    Points
    69
    Par défaut
    Bonsoir,

    Je vous propose d'abord ce début de requête, qui ne conserve que les dates les plus grandes pour champs A et champs B avec champs C = Y.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    select champsA, champsB, champsC
      from MaTable T
     where not exists
         (select 1
            from Matable T2
           where T2.champsA = T.champsA
             and T2.champsB = T.champsB
             and T2.champsD > T.champsD)
       and champsC = 'Y'
    Qui devrait renvoyer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Champs A Champs B Champs C Champs D
    nom1 5 Y 01/01/2000
    nom1 7 Y 01/01/2010
    nom2 1 Y 01/01/2000
    Dans un second temps, en repartant de ce résultat (donc avec une clause WITH), on ne conserve que les champs A avec le champs B minimum :

    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
    17
    18
    19
     
    with Etape1 as (
    select champsA, champsB, champsC
      from MaTable T
     where not exists
         (select 1
            from Matable T2
           where T2.champsA = T.champsA
             and T2.champsB = T.champsB
             and T2.champsD > T.champsD)
       and champsC = 'Y'
    )
    select *
      from Etape1 E
     where not exists
           (select 1
             from Etape1 E2
            where E2.champsA = E.champsA
              and E2.champsB < E.champsB)
    Une variante en moins performant, mais peut être plus lisible :
    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
    17
     
    with Etape1 as (
    select champsA, champsB, champsC
      from MaTable T
     where T.champsD =
         (select max(T2.ChampsD)
            from Matable T2
           where T2.champsA = T.champsA
             and T2.champsB = T.champsB)
       and champsC = 'Y'
    )
    select *
      from Etape1 E
     where E.champsB =
           (select min(E2.champsB)
             from Etape1 E2
            where E2.champsA = E.champsA)

    Cdlt,
    OD

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Une autre solution avec un seul table scan :
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    with MaTable as
    (
    select 'nom1' as c1, 1 as c2, 'N' as c3, to_date('01/01/2000', 'dd/mm/yyyy') as c4 from dual union all
    select 'nom1'      , 3      , 'N'      , to_date('01/01/2000', 'dd/mm/yyyy')       from dual union all
    select 'nom1'      , 3      , 'Y'      , to_date('31/12/1999', 'dd/mm/yyyy')       from dual union all
    select 'nom1'      , 5      , 'Y'      , to_date('01/01/2000', 'dd/mm/yyyy')       from dual union all
    select 'nom1'      , 5      , 'N'      , to_date('31/12/1999', 'dd/mm/yyyy')       from dual union all
    select 'nom1'      , 7      , 'Y'      , to_date('01/01/2010', 'dd/mm/yyyy')       from dual union all
    select 'nom1'      , 7      , 'N'      , to_date('31/12/2000', 'dd/mm/yyyy')       from dual union all
    select 'nom2'      , 1      , 'Y'      , to_date('01/01/2000', 'dd/mm/yyyy')       from dual union all
    select 'nom2'      , 1      , 'N'      , to_date('01/01/2000', 'dd/mm/yyyy')       from dual
    )
      ,  sr1 as
    (
    SELECT c1, c2, c3, c4,
           case 
             when max(c3) over(partition by c1, c2) = 'Y'
              and max(c4) over(partition by c1, c2) = c4
             then 1
           end as c5
      from MaTable
    )
      ,  sr2 as
    (
    select c1, c2, c3, c4,
           row_number() over(partition by c1 order by c2 asc) as rn
      from sr1
     where c3 = 'Y'
       and c5 = 1
    )
    select c1, c2, c3, c4
      from sr2
     where rn = 1;

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Merci pour vos réponses, mais entre-temps j'ai trouvé la solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select a.champsA, min(a.champsB) from Table a
    where a.champsC = 'Y'
    and a.champsD = (select max(b.champsD) from Table b where a.champsA = b.champsA and a.champsB = b.champsB)
    GROUP BY a.champsA

  7. #7
    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, est-ce que votre solution marchera encore si vous rajoutez par exemple cette entrée (après je ne sais pas si ce cas de figure est possible) ?

    nom1 1 Y 01/12/2000

Discussions similaires

  1. Réponses: 11
    Dernier message: 07/09/2010, 22h49
  2. Definir un nombre maximum dans une liste
    Par jjpopaul dans le forum Langage
    Réponses: 1
    Dernier message: 13/04/2010, 16h48
  3. le maximum dans une liste
    Par anissben dans le forum Caml
    Réponses: 8
    Dernier message: 22/06/2009, 19h53
  4. Réponses: 6
    Dernier message: 15/11/2008, 16h06
  5. recherche de la valeur maximum dans une série de cellules
    Par Lechette dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 01/04/2008, 08h33

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