web-dev-qa-db-fra.com

Ajoutez une somme cumulative à la requête de la série temps PostgreSQL 9.5

J'ai écrit la requête qui me donne des séries chronologiques sur une plage et un intervalle de date indiquant les revenus pour chaque intervalle de temps:

SELECT
    interval_date,
    coalesce(campaign_revenue,0) AS campaign_revenue,
FROM
    -- generate_series helps fill the empty gaps in the following JOIN
    generate_series(
        $2::timestamp,
        $3::timestamp,
        $4) AS interval_date -- could be '1 day', '1 hour' or '1 minute'.
LEFT OUTER JOIN
    -- This SELECT gets all timeseries rows that have data
    (SELECT
        date_trunc($4, s.created) AS interval,
        SUM(s.revenue) campaign_revenue
    FROM
        sale_event AS s
    WHERE
        s.campaignid = $1 AND s.created BETWEEN $2 AND $3 AND s.event_type = 'session_closed'
    GROUP BY
        interval) results
ON
    (results.interval = interval_date);

La requête prend chaque rangée de sale_event table, tronque la date de création à un intervalle (aligne le created horodatage avec la granularité souhaitée de la série temporelle), des groupes de cet intervalle de temps et résume les colonnes revenue sur les lignes où event_type est session_closed.

Cela fonctionne très bien et me donne les revenus dans l'intervalle spécifié. Le résultat peut ressembler à:

interval_date   |   campaign_revenue
------------------------------------
 2018-08-05     |   0.0
 2018-08-06     |   1.5
 2018-08-07     |   0.0
 2018-08-08     |   0.5
 2018-08-09     |   1.0

Lorsque la plage fournie est 2018-08-05 - 2018-08-09 et interval = '1 day'.

Je tiens à ajouter au résultat la somme des revenus jusqu'à cette date. Donc, si avant 2018-08-05 il y a un chiffre d'affaires total de 10.0, le résultat serait:

interval_date   |   campaign_revenue   |   total_campaign_revenue
-----------------------------------------------------------------
 2018-08-05     |   0.0                |   10.0
 2018-08-06     |   1.5                |   11.5
 2018-08-07     |   0.0                |   11.5
 2018-08-08     |   0.5                |   12.0
 2018-08-09     |   1.0                |   13.0
2
AlexGordon

Si je comprends bien, vous pouvez simplement ajouter une fonction de fenêtre en dehors de votre requête comme:

SELECT interval_date, campaign_revenue
     , SUM(campaign_revenue) OVER (ORDER BY interval_date) 
      + (SELECT SUM(revenue) 
         FROM sale_event
         WHERE s.campaignid = $1
           AND s.created < $2
           AND s.event_type = 'session_closed') as total_campaign_revenue
FROM (
    SELECT interval_date
         , coalesce(campaign_revenue,0) AS campaign_revenue
    FROM
        -- generate_series helps fill the empty gaps in the following JOIN
        ...
        interval) results
    ON (results.interval = interval_date)
);

Une autre option consiste à appliquer directement la fonction de fenêtre et utilisez une clause de filtrage pour campaign_revenue

3
Lennart