Postgresql中的日期限制运行平均值 - 如何划分为四个星期
Posted
技术标签:
【中文标题】Postgresql中的日期限制运行平均值 - 如何划分为四个星期【英文标题】:Date-bound running average in Postgresql - how to partition into four weeks 【发布时间】:2019-08-20 15:37:10 【问题描述】:我有一张表,其中包含 sales_date(每周:每周六)、item_ID 和 sales。我想要一个四个星期的运行平均值。我需要将我的数据划分为每个 ID 为期 4 周的部分,但我不知道如何执行语法。
示例表:
ID date value four_wk_average
<p>123 04/05/2019 1640.88 1640.88
<p>123 11/05/2019 2093.4 1867.14
<p>123 18/05/2019 2671.57 2135.28
<p>123 25/05/2019 2034.6 2110.11
<p>123 01/06/2019 1564.62 2001.01
<p>123 08/06/2019 2143.29 2024.73
<p>123 15/06/2019 2007 2022.19
<p>123 22/06/2019 2329.35 2060.59
<p>123 29/06/2019 2794.32 2142.11
<p>123 06/07/2019 3380.05 2265.91
当我运行下面的代码时,我得到了最右边的列 - 这是一个运行平均值,但它需要所有行,而不仅仅是我想要的当前行和前三行。
select
id,
date,
value,
avg(value) over (partition by id, (x.date between x.date and x.date - '22 days'::interval) order by date)
from
(select id, date::date, value from sales where date >= '2019-05-01') x
正确的值是
ID date value four_wk_average
<p>123 04/05/2019 1640.88 1640.88
<p>123 11/05/2019 2093.4 1867.14
<p>123 18/05/2019 2671.57 2135.28
<p>123 25/05/2019 2034.6 2110.11
<p>123 01/06/2019 1564.62 2091.05
<p>123 08/06/2019 2143.29 2103.52
<p>123 15/06/2019 2007 1937.38
<p>123 22/06/2019 2329.35 2011.07
<p>123 29/06/2019 2794.32 2318.49
<p>123 06/07/2019 3380.05 2627.68
我认为我的分区将我的间隔部分作为布尔测试并返回 TRUE - 我不知道如何在窗口函数中表示日期范围。
谢谢!
【问题讨论】:
【参考方案1】:demo:db<>fiddle
方式 1:这适用于 Postgres 11+ 和每周几条记录
SELECT
*,
AVG(value) OVER (ORDER BY the_date RANGE BETWEEN interval '4 weeks - 1 day' PRECEDING AND CURRENT ROW)
FROM
sales
间隔为 4 周:4 周减去 1 天加上当天。
方式 2:这也适用于 Postgres 并且仅当确实每周只有一条记录:
SELECT
*,
AVG(value) OVER (ORDER BY the_date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
FROM
sales
Further reading 关于窗口函数和ROWS
和RANGE
子句
方式 3:这是 Postgres 版本 和 每周几条记录的方式:
SELECT
s1.*,
(SELECT AVG(s2.value)
FROM sales s2
WHERE s2.the_date <= s1.the_date
AND s2.the_date > s1.the_date - interval '4 weeks')
FROM sales s1;
【讨论】:
Lifesaver:我使用了方式 2,效果很好。也感谢您的进一步阅读 - 我试图在互联网上搜索如何做到这一点,但我找不到任何东西。再次感谢。 嗨!我很抱歉没有早点回答。当我将所有数据放在一起时,这不起作用 - 在这种情况下,数据按国家和 ID 分组。您的三个选项中哪一个最适合这种情况?以 Excel 的方式思考,我想做一个 AVERAGEIFS,条件是 ID 和国家/地区匹配。或者我可以对我正在执行此操作的子查询进行任何排序,以使 PRECEDING ROW 语法起作用?谢谢! 不过,我当然可以尝试帮助您。但在那种情况下,我也确实需要样本数据和预期输出。所以请尝试创建一个小提琴(就像我在回答中所做的那样)和/或打开一个全新的问题!以上是关于Postgresql中的日期限制运行平均值 - 如何划分为四个星期的主要内容,如果未能解决你的问题,请参考以下文章
(运行的干净代码)根据来自另一个数据帧的日期间隔和字符串条件获取一个数据帧中的值的平均值