使用 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;
另一种方法是利用 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;
两者都生成此输出:
请注意,我的 school_id=1
输出与您的预期输出不一致,但我认为您的预期数据有错字。
我有一个 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;
另一种方法是利用 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;
两者都生成此输出:
请注意,我的 school_id=1
输出与您的预期输出不一致,但我认为您的预期数据有错字。