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 PostgreSQL Discussion :

Sauf le dernier de chaque sous ensemble


Sujet :

Requêtes PostgreSQL

  1. #1
    Membre habitué
    Homme Profil pro
    Master Data Manager
    Inscrit en
    Février 2017
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Master Data Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2017
    Messages : 113
    Points : 148
    Points
    148
    Par défaut Sauf le dernier de chaque sous ensemble
    Bonjour.

    J'ai besoin de collecter les 'id' de 'ma_table' sauf le dernier de chaque sous-ensemble d'un autre champ. Avec le code qui suit, cela devrait être plus clair:

    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
    create table ma_table (
    id serial,
    val char(1)
    )
     
    insert into ma_table ( val )
    values 
    ('A'),
    ('B'),
    ('A'),
    ('B'),
    ('B'),
    ('A'),
    ('C'),
    ('C')
     
    select * from ma_table
    Retourne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     id | val
    ----+-----
      1 | A
      2 | B
      3 | A
      4 | B
      5 | B
      6 | A
      7 | C
      8 | C
    (8 lignes)
    Donc je veux récupérer les id (1,2,3,4 et 7).

    J'ai trouvé une solution, mais j'ai peur d'avoir fait trop compliqué, et comme cette solution doit intégrer un ensemble plus complexe, j'aimerai la simplifier au maximum pour ne pas accroitre inutilement la complexité du projet final.

    Voici la solution:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    select B.id
    from (
    	select *
    	     , max(A.rank) over ( partition by A.val ) as rank_max
    	from ( select *
    		    , rank() over ( partition by val order by id ) as rank 
    		 from ma_table 
    	     ) as A
         ) AS B
    where not B.rank_max = B.rank
    Les critiques ou autres solutions sont les bienvenus

  2. #2
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 016
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 016
    Points : 23 705
    Points
    23 705
    Par défaut
    Bonjour,

    Une écriture "plus simple" à mon sens (la notion de simplicité est toute relative) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select id
    from ma_table
    except
    select max(id) 
    from ma_table
    group by val
    order by id;
    Après, il faut aussi comparer les performances des différentes écritures...

    @+
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  3. #3
    Membre habitué
    Homme Profil pro
    Master Data Manager
    Inscrit en
    Février 2017
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Master Data Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2017
    Messages : 113
    Points : 148
    Points
    148
    Par défaut
    Bonjour ced.

    Merci pour votre réponse.

    Je trouve votre solution plus élégante que la mienne, car:

    1. pas de sous-requêtes ni de fonction de fenêtrage
    2. pas de création de nouvelles donnée pour répondre au problème
    3. plus simple à lire

    Je vois difficilement comment avoir une réponse plus simple a mon problème ( avis aux amateurs )

    Je prends votre solution (encore merci) et je coche résolu !

  4. #4
    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
    Un ajout à la solution de ced, faites un EXCEPT ALL au lieu d'un EXCEPT, vous économiserez un distinct.

    La solution avec les fonctions de fenêtrage n'est pas à jeter à la poubelle, mais vous l'avez rédigée plus compliquée que nécessaire.
    Une version plus simple serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    with cte_matable (id, val, rn) as
    (
    select id, val, row_number() over(partition by val order by id desc)
      from matable
    )
    select id, val
      from cte_matable
     where rn > 1;

  5. #5
    Membre habitué
    Homme Profil pro
    Master Data Manager
    Inscrit en
    Février 2017
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Master Data Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2017
    Messages : 113
    Points : 148
    Points
    148
    Par défaut
    Bonjour Waldar.

    Merci de votre réponse que je trouve maligne.

    Par contre je me demande quel avantage y a-t-il à utiliser un 'with' plutôt qu'une sous-requête comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select A.id
      from ( select id, val, row_number() over(partition by val order by id desc) AS rn from ma_table ) as A
    where A.rn > 1
    Juste une question de lisibilité ou y a il un autre avantage ?

  6. #6
    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
    C'est en effet plus lisible ; notamment quand plusieurs sous-requêtes s'imbriquent.
    Mais surtout c'est réutilisable plusieurs fois - et construit une seule fois, encore que sur pg je n'en suis pas certain.

  7. #7
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 016
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 016
    Points : 23 705
    Points
    23 705
    Par défaut
    Surtout, par rapport à ma requête, la requête avec CTE présente l'avantage (en termes de performances) de ne parcourir qu'une seule fois ma_table.
    C'est donc plus performant dans le cas présent.

    Les CTE sont effectivement utilisables plusieurs fois dans une même requête sous PostgreSQL.
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

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

Discussions similaires

  1. Derniers fichiers dans un ensemble de sous dossier avec les dates
    Par tanaka59 dans le forum Windows Serveur
    Réponses: 1
    Dernier message: 03/08/2016, 15h53
  2. Afficher le dernier MP3 de chaque sous dossier
    Par dercom dans le forum Langage
    Réponses: 2
    Dernier message: 31/01/2015, 21h54
  3. sous ensemble d'une liste
    Par adel25 dans le forum C++
    Réponses: 1
    Dernier message: 23/08/2005, 15h50
  4. [DBGrid] Affichage d'un sous-ensemble de données
    Par Jean-Jacques Engels dans le forum Bases de données
    Réponses: 3
    Dernier message: 02/09/2004, 16h31
  5. Sous-ensembles de tuples
    Par HPJ dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 07/10/2003, 16h24

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