SQL中的滚动平均值,而不使用中间值
假设我有一个表格,其注册格式如下:SQL中的滚动平均值,而不使用中间值,sql,date,select,group-by,window-functions,Sql,Date,Select,Group By,Window Functions,假设我有一个表格,其注册格式如下: | date | sign_ups | |------------|----------| | 2018-01-01 | 34 | | 2018-01-02 | 23 | | 2018-01-03 | 2 | | ... | ... | 现在我想写一个查询来计算前7天的平均注册数,即给定一天的平均注册数和前6天的注册值。这提供了以下解决方案: select date, avg(
| date | sign_ups |
|------------|----------|
| 2018-01-01 | 34 |
| 2018-01-02 | 23 |
| 2018-01-03 | 2 |
| ... | ... |
现在我想写一个查询来计算前7天的平均注册数,即给定一天的平均注册数和前6天的注册值。这提供了以下解决方案:
select
date,
avg(sign_ups)
over (order by date asc
rows between 6 preceding and current row) as avg,
from signups
我不喜欢在两者之间使用SQL,因此我编写了以下解决方案:
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
只是想确认这两者是等价的,以及是否有更简洁/更有效的解决方案 首先,假设你的意思是:
on b.date <= a.date and
b.date > interval '7 days'
那么,只有在每个日期只有一行的情况下,它们才是等价的
您的版本完全不同-您在联接中的日期之后但在windows函数中的日期之前获取值。一种情况下有8个值,另一种情况下有一些未知数。但我明白了问题的要点
窗口函数版本比自联接更受欢迎。从性能和可理解性的角度来看,这简直更好。而且,正如您的代码充分展示的那样,windows版本更容易表达您的实际意图。首先,假设您的真正意思是:
on b.date <= a.date and
b.date > interval '7 days'
那么,只有在每个日期只有一行的情况下,它们才是等价的
您的版本完全不同-您在联接中的日期之后但在windows函数中的日期之前获取值。一种情况下有8个值,另一种情况下有一些未知数。但我明白了问题的要点
窗口函数版本比自联接更受欢迎。从性能和可理解性的角度来看,这简直更好。而且,正如您的代码充分展示的那样,windows版本更容易表达您的实际意图。这两个查询并不等价: 1正如@GordonLinoff所回答的,第一个查询返回的记录与表中的记录一样多,而第二个查询按日期进行聚合。为了使结果相同,每个日期应该只有一行 2这是:
rows between 6 preceding and current row
不等同于:
a.date <= b.date + interval '7 days'
这两个查询并不等同: 1正如@GordonLinoff所回答的,第一个查询返回的记录与表中的记录一样多,而第二个查询按日期进行聚合。为了使结果相同,每个日期应该只有一行 2这是:
rows between 6 preceding and current row
不等同于:
a.date <= b.date + interval '7 days'
你不喜欢中间的????你不应该从语言语法中挑选朋友。它起作用了。它能有效地完成工作。你还想要什么?为什么不直接运行这两个程序并比较结果呢?很容易发现第二个返回完全不同的东西。你不喜欢中间????你不应该从语言语法中挑选朋友。它起作用了。它能有效地完成工作。你还想要什么?为什么不直接运行这两个程序并比较结果呢?很容易发现第二个返回了完全不同的结果。即使在重写之后,它的平均时间仍然是8天,而不是7天:-@dnoeth:啊,是的,你是对的,我没有注意到这一点。。。我更新了我的答案:即使在重写之后,它的平均时间仍然是8天而不是7天:-@dnoeth:啊,是的,你是对的,我没有注意到这一点。。。我更新了我的答案: