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 :

Requête de calcul


Sujet :

Requêtes PostgreSQL

  1. #1
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut Requête de calcul
    Bonjour,
    Voila je suis un peu embêté car je ne suis pas un AS en requêtes SQL et j'aurais du coup besoin de votre aide.

    Je possède 2 tables
    -GiftCard (id, amount)
    -Transaction(id, amount, GiftCard, created_at)

    Ce que je tente de générer comme tableau

    GiftCard id Trasaction id Transaction amount Amount Date
    1 8 -3,20 € 8,43 € 10/9/2020
    1 7 -33,37 € 11,63 € 25/7/2020
    1 6 45,00 € 45,00 € 30/12/2019
    1 5 -28,79 € 0,00 € 16/5/2018
    1 4 -21,21 € 28,79 € 12/7/2017
    1 3 50,00 € 50,00 € 8/5/2017
    1 2 -10 € 0,00 € 20/9/2016
    1 1 10 € 10 € 19/9/2016

    Je possède donc GiftCard id, Transaction id, Transaction amount et Date.
    En ce qui concerne Amount je ne possède que la valeur final, à savoir 8,43€ dans l'exemple.
    Comment puis-je faire une requête se basant sur la valeur précédente pour calculer la valeur suivant?
    Est-il possible de le faire directement avec une requête SQL ou dois-je passer par du PL/SQL?

    Merci d'avance,
    Sparky

  2. #2
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    A vérifier...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select c.id as giftcard_id, t.id as transaction_id, t.amount as transaction_amount, 
    --la somme des transactions antérieures plus le montant de la transaction en cours
    (select sum(t2.amount) from trasaction as t2 where t.giftcard=t2.giftcard and t2.id<=t.id) as amount_ligne
    date
    from giftcard as c inner join trasaction as t on c.id=t.giftcard
    NB: ici j'utilise t2.id<=t.id mais il est mieux de faire t2.date<=t.date si les transaction ont des dates!
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  3. #3
    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
    Citation Envoyé par alassanediakite Voir le message
    NB: ici j'utilise t2.id<=t.id mais il est mieux de faire t2.date<=t.date si les transaction ont des dates!
    @+
    Non seulement il vaut mieux, mais surtout il ne faut jamais utiliser des id de type serial (attribués par le SGGBD) comme critère chronologique.
    Il n'y a aucune garantie que les n° soient attribués dans l'ordre chronologique.
    Il faut donc s'appuyer sur la colonne date en utilisant par exemple la fonction LAG() pour rechercher la valeur de la ligne précédente.
    cf. https://www.postgresql.org/docs/8.4/...ns-window.html

  4. #4
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    Nickel cela fonctionnes
    Merci beaucoup


    Ajout:
    @escartefigue J'ai lu la documentation concernant la fonction LAG qui permets donc de ce déplacer d'x étape(s) cependant, je n'ai pas réussi à générer la requête qui utiliserait la méthode
    Code sql : 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
    34
    35
    36
    37
    38
    39
    40
    41
     
    DROP TABLE IF EXISTS gift_cards CASCADE;
    DROP TABLE IF EXISTS transactions;
     
     
    CREATE TABLE gift_cards(
        id INT PRIMARY KEY,
        amount NUMERIC(15, 5)
    );
     
     
    CREATE TABLE transactions(
        id SERIAL PRIMARY KEY,
        payment NUMERIC(15, 5),
        gift_card_id INT,
        created_at TIMESTAMP,
        FOREIGN KEY (gift_card_id) REFERENCES gift_cards(id)
    );
     
     
    INSERT INTO gift_cards(id, amount) VALUES (1, 8.43);
     
     
    INSERT INTO transactions(payment, gift_card_id, created_at) VALUES (10, 1, '19/09/2016');
    INSERT INTO transactions(payment, gift_card_id, created_at) VALUES (-10, 1, '20/09/2016');
    INSERT INTO transactions(payment, gift_card_id, created_at) VALUES (50, 1, '08/05/2017');
    INSERT INTO transactions(payment, gift_card_id, created_at) VALUES (-21.21, 1, '12/07/2017');
    INSERT INTO transactions(payment, gift_card_id, created_at) VALUES (-28.79, 1, '16/05/2018');
    INSERT INTO transactions(payment, gift_card_id, created_at) VALUES (45, 1, '30/12/2019');
    INSERT INTO transactions(payment, gift_card_id, created_at) VALUES (-33.37, 1, '27/07/2020');
    INSERT INTO transactions(payment, gift_card_id, created_at) VALUES (-3.20, 1, '10/09/2020');
     
     
     
     
    SELECT c.id AS gift_card_id, t.id AS transaction_id, t.payment AS transaction_payment, 
    --la somme des transactions antérieures plus le montant de la transaction en cours,
    (SELECT SUM(t2.payment) FROM transactions AS t2 WHERE t.gift_card_id = t2.gift_card_id AND t2.created_at <= t.created_at) AS amount_ligne,
    LAG(t.payment, 1) OVER ( ORDER BY created_at) --si j'ai bien suivi le but est de remplacer le select du dessus par le LAG ?
    created_at
    FROM gift_cards AS c INNER JOIN transactions AS t ON c.id = t.gift_card_id;

    Voici une copie de mon code de test.


    Merci d'avance pour votre aide,
    Sparky

  5. #5
    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 Sparky95,


    À cette question
    Citation Envoyé par Sparky95 Voir le message
    Comment puis-je faire une requête se basant sur la valeur précédente pour calculer la valeur suivant(e) ?
    Est-il possible de le faire directement avec une requête SQL ou dois-je passer par du PL/SQL?
    J'avais proposé la fonction LAG() qui permet de récupérer les n valeurs précédentes, n valant 1 par défaut.
    Mais, si la solution proposée par alassanediakite convient, c'est que l'expression de besoin n'est pas bien formulée : c'est le cumul de toutes les valeurs précédentes qui est recherché et non pas la valeur précédente seulement.
    En ce cas, LAG() ne conviendra pas.

    Mais, comme expliqué précédemment, la solution est applicable sous réserve de remplacer la restriction sur identifiants inférieurs par une restriction sur dates inférieures.

  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
    Comme ceci :
    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
      select gift_card_id
           , id             as transaction_id
           , payment        as transaction_amount
           , sum(payment) over(partition by gift_card_id order by created_at asc) as amount
           , created_at
        from transactions
    order by created_at desc;
     
    gift_card_id  transaction_id  transaction_amount  amount    created_at
    ------------  --------------  ------------------  --------  ----------
               1               8           - 3.20000   8.43000  2020-09-10
               1               7           -33.37000  11.63000  2020-07-27
               1               6            45.00000  45.00000  2019-12-30
               1               5           -28.79000   0.00000  2018-05-16
               1               4           -21.21000  28.79000  2017-07-12
               1               3            50.00000  50.00000  2017-05-08
               1               2           -10.00000   0.00000  2016-09-20
               1               1            10.00000  10.00000  2016-09-16

  7. #7
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    Merci Waldar

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

Discussions similaires

  1. [SQL] Grosse requête SQL + calculs
    Par nicopoal dans le forum PHP & Base de données
    Réponses: 22
    Dernier message: 19/01/2007, 14h18
  2. Requête pour calculer le temps entre deux dates
    Par Badboy62cfp dans le forum Access
    Réponses: 2
    Dernier message: 19/05/2006, 13h50
  3. Ma requête ne calcul pas pour tout les champs
    Par leloup84 dans le forum Requêtes
    Réponses: 10
    Dernier message: 01/03/2006, 12h59
  4. Ma requête ne calcul pas pour tout les champs
    Par leloup84 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 01/03/2006, 10h11
  5. [Debutant]Problème Requête et Calcul
    Par ghan77 dans le forum Bases de données
    Réponses: 9
    Dernier message: 04/01/2006, 14h47

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