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 :

Script de mise à jour de données par parcours de ligne.


Sujet :

PostgreSQL

  1. #1
    Membre habitué
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2009
    Messages : 311
    Points : 127
    Points
    127
    Par défaut Script de mise à jour de données par parcours de ligne.
    Bonjour à tous,

    je voudrais savoir s'il était possible de créer un script sous postgresql qui permettrait de lire les données d'une table et d'en faire un cumul pour mettre à jour un champ d'une autre ligne de cette table.

    Plus précisément, dans cette table mes contiennent un champ type_ligne qui peut prendre les valeurs (1,2,3,4,5).
    par exemple :
    id, code, type_ligne, montant
    1 , AAA , 2 , 0
    2 , AAA , 4 , 10
    3 , AAA , 5 , 23
    4 , AAA , 4 , 16
    5 , AAA , 5 , 45
    6 , AAA , 2 , 0
    7 , AAA , 3 , 27
    8 , AAA , 3 , 11
    8 , AAA , 1 , 10
    9 , BBB , 1 , 42
    etc...

    Je voudrais mettre à jour toutes les lignes ayant pour "type_ligne" = 2 par le cumul des types ligne 3,4,5 celle qui se suivent uniquement jusqu'à rencontrer un type ligne différent de (3,4,5). Après calcul, ces lignes doivent être effacées !
    C'est-à- dire que après le passage du script mon tableau doit ressembler à ça :
    code, type_ligne, montant
    1 , AAA , 2 , 94 ====> (94=10+23+16+45)
    6 , AAA , 2 , 38 ====> (38 = 27+11)
    8 , AAA , 1 , 10
    9 , BBB , 1 , 42
    etc...

    J'ai essayé d'utiliser sum() mais il me prend toutes les lignes, ce n'est pas ce que je veux.
    Est-ce que c'est possible d'utiliser un WHILE ? Quelle serait la syntaxe ?

    Je vous remercie par avance.

  2. #2
    Membre habitué
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2009
    Messages : 311
    Points : 127
    Points
    127
    Par défaut
    J'ai avancé un peu, je me suis lancé dans une fonction:
    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
     
    CREATE OR REPLACE Function c_cprpri(num varchar,lig integer,typel integer) RETURNS real AS $$
    DECLARE
    rec RECORD;
    curs refcursor;
    v_cprpri REAL Default 0;
     
    BEGIN
    OPEN curs FOR SELECT * FROM fact_sih_soh WHERE numero=num AND ligne_piece >lig;
    IF (typel = 2 or typel = 6)  THEN 
        LOOP
            FETCH curs INTO rec;
            EXIT WHEN rec.type_ligne not in (3,4,5,7,8,9);
            v_cprpri := v_cprpri+rec.cprpri_fac;
        END LOOP;
    END IF;
    CLOSE curs;
    return abs(v_cprpri);
    END
    $$ LANGUAGE plpgsql;
    Seulement voilà, lorsque je lance un tester via phppgadmin , je n'ai pas d'erreur mais la requête tourne sans fin...
    Mon code est-il correct ?

    Merci

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

    Pour le code, je n'ai pas regardé.

    Par contre votre démarche est mauvaise.

    SQL est un langage ensembliste, du coup quand on l'utilise, il faut arrêter de penser itératif.

    Bref, commencez par faire la requête qui somme les montants en regroupant par code, tout en excluant les types non voulu.
    Vous aurez besoin d'un NOT IN pour la clause WHERE et d'un GROUP BY pour la clause de regroupement.

    Ensuite passez à la requête de mise à jour, puis à celle de suppression.

  4. #4
    Membre habitué
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2009
    Messages : 311
    Points : 127
    Points
    127
    Par défaut
    Bonjour,

    Tout d'abord, merci d'avoir répondu à ce poste. Concernant ma démarche, je suis obligé de penser "itératif" puisque la seule information de "rupture" est contenu dans les lignes suivantes.

    La fonction ci-dessus (que je viens de modifier) semble fonctionner, sauf pour un ensemble particulier de lignes. Je reviens sur le post dès que j'ai des réponses plus précises.

    En attendant, pouvez-vous me dire si cette fonction vous semble correct ?

    Merci encore

  5. #5
    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
    Dans une table il n'y a pas d'ordre au niveau des lignes.

    Vous n'avez pas spécifié de clause order by dans votre requête du coup elle ne fonctionnera pas.


    Sinon votre "rupture" peut être modélisée dans une requête sans trop de problème (not exists)

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Comme l'a indiqué punkoff, il n'y a pas d'ordre dans une table, on va supposer que vous voulez vous appuyer la colonne id...
    On va supposer aussi que cette colonne est unique (et que votre jeu d'essai contient une erreur : le 8 en doublon)

    A partir de là, on peut faire en deux étapes : mise à jour avec les sommes, puis suppression des lignes dont le type est 3, 4 ou 5 :

    Avec un jeu d'essai :
    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
     
     
    CREATE TABLE LaTable(
        id int not null primary key,
        code varchar(10),
        type_ligne int,
        montant int
    );
     
    INSERT INTO LaTable VALUES(1 , 'AAA' , 2 , 0);
    INSERT INTO LaTable VALUES(2 , 'AAA' , 4 , 10);
    INSERT INTO LaTable VALUES(3 , 'AAA' , 5 , 23);
    INSERT INTO LaTable VALUES(4 , 'AAA' , 4 , 16);
    INSERT INTO LaTable VALUES(5 , 'AAA' , 5 , 45);
    INSERT INTO LaTable VALUES(6 , 'AAA' , 2 , 0);
    INSERT INTO LaTable VALUES(7 , 'AAA' , 3 , 27);
    INSERT INTO LaTable VALUES(8 , 'AAA' , 3 , 11);
    INSERT INTO LaTable VALUES(9 , 'AAA' , 1 , 10);
    INSERT INTO LaTable VALUES(10 , 'BBB' , 1 , 42);
    Mise à jour des sommes
    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
     
    ;WITH CTE AS (
        SELECT 
            A.id,
            A.code,
            A.type_ligne,
            A.montant,
            SUM(A.montant) OVER(PARTITION BY COUNT(B.id)) AS Somme
        FROM LaTable A
        INNER JOIN LaTable B
            ON    B.id <= A.id
            AND B.type_ligne NOT IN (3,4,5)
        GROUP BY 
            A.id,
            A.code,
            A.type_ligne,
            A.montant
    )
    UPDATE LaTable
      SET montant = Somme
    FROM CTE
    WHERE CTE.id = LaTable.id
    AND LaTable.type_ligne = 2;
    Suppression des lignes dont le type est 3,4 ou 5
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    DELETE FROM LaTable
    WHERE Type_ligne IN (3,4,5);
    ce qui donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM LaTable
    ORDER BY id;
    ID CODE TYPE_LIGNE MONTANT
    1 AAA 2 94
    6 AAA 2 38
    9 AAA 1 10
    10 BBB 1 42

  7. #7
    Membre habitué
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2009
    Messages : 311
    Points : 127
    Points
    127
    Par défaut
    Merci pour toutes vos informations, je clos le sujet .

    Merci à tous.

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

Discussions similaires

  1. [XL-2007] Mise à jour des données par formulaire vba Excel
    Par rattus34 dans le forum Macros et VBA Excel
    Réponses: 12
    Dernier message: 16/02/2012, 12h48
  2. [XL-2010] Mise à jour des données par formulaire vba Excel
    Par mam51100 dans le forum Excel
    Réponses: 0
    Dernier message: 16/02/2012, 10h25
  3. Mise à jour des données par macros.
    Par chpierro62 dans le forum Macros et VBA Excel
    Réponses: 16
    Dernier message: 12/01/2012, 13h52
  4. Réponses: 7
    Dernier message: 20/08/2009, 01h48
  5. Installer plusieurs mises à jours de Windows par Script
    Par bbkenny dans le forum Windows Serveur
    Réponses: 2
    Dernier message: 26/05/2009, 17h57

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