使用 psql,你如何获得最近 3 天的总和,每一天?

Using psql, how do you get the total sum for last 3 days, on each day?

我有一个 table,其中包含在每所学校进行的所有购买。我能够得到每所学校、每件物品、每天的总花费, 与以下。

SELECT
 date
 school_id,
 item_id, 
 sum(price) as total_price
 FROM purchases
 GROUP BY school_id, item_id, date
 ORDER BY school_id, date

它将return类似于

date         school_id  item_id   total_price
 2016-11-18 |      1   |      1   |        0.50
 2016-11-17 |      1   |      2   |        1.00
 2016-11-16 |      1   |      1   |        0.50
 2016-11-18 |      2   |      2   |        1.00
 2016-11-17 |      2   |      2   |        1.00
 2016-11-16 |      2   |      2   |        1.00

我需要一个table,即return每天最后3天(包括当天)的总价, 所以像

 date         school_id  item_id   total_price
 2016-11-18 |      1   |      1   |        1.00
 2016-11-17 |      1   |      2   |        1.00
 2016-11-16 |      1   |      1   |        0.50
 2016-11-18 |      2   |      2   |        3.00
 2016-11-17 |      2   |      2   |        2.00
 2016-11-16 |      2   |      2   |        1.00

我知道我可以在 (PARTITION BY) 上使用 lag(),但我可能需要一次执行此操作数月而不是 3 天,并且延迟将永远无法设置。 我不太确定我还能使用什么其他方法。有指导吗?

一个简单的 INNER JOIN 就可以了 您将 table 加入自身,当学校和项目匹配时,日期为 3 天范围

请注意,这会给出过去 3 天的移动平均值,但从你的问题来看似乎是这样,因为你想要连续几天,没有跳跃

SELECT
 p1.date
 p1.school_id,
 p1.item_id, 
 SUM(p2.price) total_price_3_days

purchases p1
INNER JOIN purchases p2 ON p1.school_id = p2.school_id AND p1.item_id = p2.item_id AND p2.`date` BETWEEN DATE_SUB(p1.`date`, INTERVAL 3 DAY) AND p1.`date`
 GROUP BY p1.school_id, p1.item_id, p1.date
 ORDER BY p1.school_id, p1.date

一种方法是在 select 子句中使用相关子查询:

SELECT
    date,
    school_id,
    item_id, 
    (SELECT SUM(p2.price) FROM purchases p2
     WHERE p1.school_id = p2.school_id AND
           p2.date BETWEEN p1.date - INTERVAL '3 DAY' AND p1.date) AS total_price
FROM purchases p1
GROUP BY school_id, item_id, date
ORDER BY school_id, date DESC;

Demo

另一种方法是利用 Postgres 的 window 函数:

SELECT
    date,
    school_id,
    item_id, 
    SUM(price) OVER (PARTITION BY school_id
        ORDER BY date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS total_price
FROM purchases p1
GROUP BY school_id, item_id, date
ORDER BY school_id, date DESC;

Demo

两者都生成此输出:

请注意,我的 school_id=1 输出与您的预期输出不一致,但我认为您的预期数据有错字。