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

 PostgreSQL Discussion :

Sequence et Groupby


Sujet :

PostgreSQL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 90
    Points : 62
    Points
    62
    Par défaut Sequence et Groupby
    Bonjour à tous,

    Je dois utiliser les sequences dans une table mais d'une facon particuliere :
    J'ai une table contenant des colonnes A (qui ont pour valeur 1,2,3,4) et des colonnes B (qui est en fonction de A), qui ont pour valeur des entiers plus ou moins ordonnés et que je cherche à renuméroter.

    Pour cela, je crée une nouvelle colonne : renumB et j'essaie d'utiliser ma séquence pour lui donner une valeur. Le problème est que je voudrais que la renumerotation se fasse pour chaque valeur de A :

    A B renumB
    ----------------
    1 1 1
    1 3 2
    1 4 3
    2 2 1
    2 3 2
    ----------------

    Voilà alors je n'arrive pas à "grouper" mon renumB sachant que je ne peux pas utiliser les boucles.

    Si quelqu'un a une petite idée

    Merci beaucoup & bonne journée,

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 719
    Points
    52 719
    Billets dans le blog
    5
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TABLE T (A INT, B INT)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    INSERT INTO T VALUES (1, 1)
    INSERT INTO T VALUES (1, 3)
    INSERT INTO T VALUES (1, 4)
    INSERT INTO T VALUES (2, 2)
    INSERT INTO T VALUES (2, 3)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT A, B, ROW_NUMBER() OVER(PARTITION BY A ORDER BY B) AS Renum
    FROM T
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    A           B           Renum
    ----------- ----------- --------------------
    1           1           1
    1           3           2
    1           4           3
    2           2           1
    2           3           2

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre expérimenté Avatar de scheu
    Inscrit en
    Juin 2007
    Messages
    1 506
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 1 506
    Points : 1 734
    Points
    1 734
    Par défaut
    Malheureusement les fonctions de fenêtrage n'existent pas (encore) sur Postgresql
    La théorie, c'est quand on sait tout mais que rien ne fonctionne.
    La pratique, c'est quand tout fonctionne mais que personne ne sait pourquoi.
    Ici, nous avons réuni théorie et pratique : Rien ne fonctionne ... et personne ne sait pourquoi !

    Réplication de base avec Postgresql : http://scheu.developpez.com/tutoriel.../log-shipping/

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 90
    Points : 62
    Points
    62
    Par défaut
    Ah c'est bien dommage, parce que ça aurait autrement plus pratique.

    A défaut la solution suivante est possible, qui n'est peut être pas des plus optimisées mais qui offre l'avantage d'être plus rapide que mes boucles.

    Je crée une nouvelle table T2 qui est la copie conforme de ma table sauf que je l'ordonne correctement par A,B. Je lui rajoute une colonne serial seq ainsi qu'une colonne renumB.

    A B seq renumB
    ----------------
    1 2 1
    1 3 2
    1 4 3
    2 1 4
    2 3 5
    3 1 6
    Ensuite je crée une deuxième table qui contient selon la table A la première valeur de seq pour chaque nouveau A :

    A min_seq
    -----------
    1 1
    2 4
    3 6

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    create table TableTemp as select A, min(seq) as min_seq from T2 
    group by A order by A;
    Et après la formule magique:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    UPDATE t2 t2 set renumB = t2.seq - temp.min_seq + 1 
    from TableTemp temp where t2.A=temp.A;
    A B seq renumB
    ----------------
    1 2 1 1
    1 3 2 2
    1 4 3 3
    2 1 4 1
    2 3 5 2
    3 1 6 1

    Si vous avez mieux, je suis super preneuse

    Bonne journée à tous,

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Effectivement c'est un problème difficile en SQL de base, sans les fonctions de fenêtrage, mais c'est quand même jouable en s'appuyant sur les tableaux et la fonction generate_series()
    D'abord il faut créer l'aggrégat array_accum si tu ne l'as pas déjà dans ta base:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE AGGREGATE array_accum (anyelement)
    (
        sfunc = array_append,
        stype = anyarray,
        initcond = '{}'
    );
    (cette fonction est dans la doc de postgresql, elle transforme une colonne en tableau)

    Ensuite le principe est de
    1- transformer la colonne B en tableau trié pour chaque A distinct
    2- récupérer la taille de ce tableau pour chaque A
    3- pour obtenir la séquence renumb, appliquer generate_series(1, taille_tableau) pour chaque A
    4- enfin pour chaque A et chaque valeur de la séquence, l'utiliser comme indice dans le tableau pour ressortir la valeur correspondante de B

    Ces 4 étapes se combinent dans une seule requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT  a,arrb[b2] AS b, b2 FROM
      (SELECT  a, arrb,generate_series(1,cnt) AS b2 FROM
        (SELECT a,arrb,array_upper(arrb,1) AS cnt FROM
          (SELECT a,array_accum(b) AS arrb FROM
            (SELECT a,b FROM t ORDER BY b) t1
           GROUP BY a
          ) t2
        ) t3
      ) t4
    ORDER BY 1,2;
    Ca reste à tester sur tes vraies données mais je crois que dans le principe ça répond au problème. Tout ça grâce aux tableaux qui sont très bien intégrés dans le moteur SQL de postgres

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 90
    Points : 62
    Points
    62
    Par défaut
    Merci vraiment beaucoup estofilo pour cette réponse très complète !


    Je ne connaissais pas bien le système des aggregate, mais là c'est bien plus clair.

    Merci encore !

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

Discussions similaires

  1. programmation corba: le type "sequence"
    Par Kali dans le forum CORBA
    Réponses: 4
    Dernier message: 28/08/2005, 16h09
  2. listage de triggers/sequences avec sql plus
    Par stross dans le forum Oracle
    Réponses: 52
    Dernier message: 20/04/2004, 15h41
  3. peut-on savoir si un champ a une sequence??
    Par e11137 dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 09/01/2004, 14h54
  4. voir les sequences existantes ?
    Par soniaSQL dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 25/06/2003, 16h33
  5. Réponses: 2
    Dernier message: 05/06/2002, 12h29

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