不使用 BETWEEN 的 SQL 滚动平均值
Rolling Average in SQL without using BETWEEN
假设我有一个 table signups
格式:
| date | sign_ups |
|------------|----------|
| 2018-01-01 | 34 |
| 2018-01-02 | 23 |
| 2018-01-03 | 2 |
| ... | ... |
我现在想编写一个查询来计算前 7 天的平均注册量,即对于给定的一天,它的平均注册量和前六天的注册量值。 blog post 提供了这个解决方案:
select
date,
avg(sign_ups)
over (order by date asc
rows between 6 preceding and current row) as avg,
from signups
我不喜欢使用 SQL 的 BETWEEN
,所以我写了这个解决方案:
SELECT
a.date,
AVG(b.sign_ups)
FROM
signups a
JOIN
signups b ON a.date <= b.date + interval '7 days'
GROUP BY
a.date
只是想确认两者是等价的,如果有更多concise/more有效的解决方案可以解决这个问题。
首先,假设你的意思是:
on b.date <= a.date and
b.date > interval '7 days'
只有当每个日期只有一行时,它们才等价。
您的版本完全不同——您在 join
函数中的日期 之后 但在 windows 函数中的日期之前取值。在一种情况下您有 8 个值,在另一种情况下有一些未知数。但是我明白了问题的要点。
window 函数版本比自连接更受欢迎。从性能和可理解性的角度来看,这简直更好。而且,正如您的代码充分展示的那样,windows 版本可以更轻松地表达您的实际意图。
两个查询不等价:
1) 正如@GordonLinoff 所回答的那样,第一个查询 returns 与 table 中的记录一样多,而第二个查询按日期聚合。为了使结果相同,每个日期应该只有一行
2) 这个:
rows between 6 preceding and current row
不等同于:
a.date <= b.date + interval '7 days'
首先,正如 Dnoeth 所评论的,第二种形式将计算当前日期和过去 7 天的平均值,这代表总共 8 天。
此外,第二个表格将考虑最近 N 天内的记录,以及当前日期之后的每条记录。
您需要更改该子句以向日期范围添加上限,例如:
a.date <= b.date + interval '6 days' AND a.date >= b.date
这基本上模仿了 BETWEEN
... 也可以拼写为 :
b.date BETEWEEN a.date - interval '6 days' AND a.date
假设我有一个 table signups
格式:
| date | sign_ups |
|------------|----------|
| 2018-01-01 | 34 |
| 2018-01-02 | 23 |
| 2018-01-03 | 2 |
| ... | ... |
我现在想编写一个查询来计算前 7 天的平均注册量,即对于给定的一天,它的平均注册量和前六天的注册量值。 blog post 提供了这个解决方案:
select
date,
avg(sign_ups)
over (order by date asc
rows between 6 preceding and current row) as avg,
from signups
我不喜欢使用 SQL 的 BETWEEN
,所以我写了这个解决方案:
SELECT
a.date,
AVG(b.sign_ups)
FROM
signups a
JOIN
signups b ON a.date <= b.date + interval '7 days'
GROUP BY
a.date
只是想确认两者是等价的,如果有更多concise/more有效的解决方案可以解决这个问题。
首先,假设你的意思是:
on b.date <= a.date and
b.date > interval '7 days'
只有当每个日期只有一行时,它们才等价。
您的版本完全不同——您在 join
函数中的日期 之后 但在 windows 函数中的日期之前取值。在一种情况下您有 8 个值,在另一种情况下有一些未知数。但是我明白了问题的要点。
window 函数版本比自连接更受欢迎。从性能和可理解性的角度来看,这简直更好。而且,正如您的代码充分展示的那样,windows 版本可以更轻松地表达您的实际意图。
两个查询不等价:
1) 正如@GordonLinoff 所回答的那样,第一个查询 returns 与 table 中的记录一样多,而第二个查询按日期聚合。为了使结果相同,每个日期应该只有一行
2) 这个:
rows between 6 preceding and current row
不等同于:
a.date <= b.date + interval '7 days'
首先,正如 Dnoeth 所评论的,第二种形式将计算当前日期和过去 7 天的平均值,这代表总共 8 天。
此外,第二个表格将考虑最近 N 天内的记录,以及当前日期之后的每条记录。
您需要更改该子句以向日期范围添加上限,例如:
a.date <= b.date + interval '6 days' AND a.date >= b.date
这基本上模仿了 BETWEEN
... 也可以拼写为 :
b.date BETEWEEN a.date - interval '6 days' AND a.date