奇怪的窗口函数行为
Posted
技术标签:
【中文标题】奇怪的窗口函数行为【英文标题】:Strange window function behaviour 【发布时间】:2014-02-14 23:19:27 【问题描述】:我有以下一组数据:
player | score | day
--------+-------+------------
John | 3 | 02-01-2014
John | 5 | 02-02-2014
John | 7 | 02-03-2014
John | 9 | 02-04-2014
John | 11 | 02-05-2014
John | 13 | 02-06-2014
Mark | 2 | 02-01-2014
Mark | 4 | 02-02-2014
Mark | 6 | 02-03-2014
Mark | 8 | 02-04-2014
Mark | 10 | 02-05-2014
Mark | 12 | 02-06-2014
给定两个时间范围:
02-01-2014..02-03-2014
02-04-2014..02-06-2014
我需要在给定的时间范围内获得每个玩家的平均分数。我想要达到的最终结果是:
player | period_1_score | period_2_score
--------+----------------+----------------
John | 5 | 11
Mark | 4 | 10
我想出的原始算法是:
-
使用两个值执行
SELECT
,通过将每个时间段的分数集分成两个来得出
在第一个 SELECT
之上,执行另一个,按玩家名称分组。
我被困在第 1 步:运行以下查询:
SELECT
player,
AVG(score) OVER (PARTITION BY day BETWEEN '02-01-2014' AND '02-03-2014') AS period_1,
AVG(score) OVER (PARTITION BY day BETWEEN '02-04-2014' AND '02-06-2014') AS period_2;
得到不正确的结果(注意period1
和period2
的平均分数是一样的:
player | period_1_score | period_2_score
--------+----------------+----------------
John | 5 | 5
John | 5 | 5
John | 5 | 5
John | 5 | 5
John | 5 | 5
John | 5 | 5
Mark | 4 | 4
Mark | 4 | 4
Mark | 4 | 4
Mark | 4 | 4
Mark | 4 | 4
Mark | 4 | 4
我想我并不完全了解窗口函数的工作原理......我有 2 个问题:
-
我的查询有什么问题?
我该如何正确操作?
【问题讨论】:
为什么将日期存储为字符串而不是DATE
?更糟糕的是,为什么要将它们存储在第一个日期(或月份)和最后一个年份?
我们(和 SQL-Server)如何知道 '02-06-2014'
是 6 月 2 日还是 2 月 6 日?您是否意识到,如果您将日期存储为字符串并使用这种格式,SQL-Server 将认为'02-06-2014'
的“日期”晚于“日期”'01-01-2020'
?
【参考方案1】:
您不需要窗口功能。 试试:
select
player
,avg(case when day BETWEEN '02-01-2014' AND '02-03-2014' then score else null end) as period_1_score
,avg(case when day BETWEEN '02-04-2014' AND '02-06-2014' then score else null end) as period_1_score
from <your data>
group by player
【讨论】:
Yakshemash。我建议你在 - sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/…chenqui 之间小心一点。 @BoratSagdiyev 无关 - 这个问题不涉及日期时间。 非常感谢@user102890! @user1509107。一点都不相关。这些是日期,适用相同的原则。为什么您可以将BETWEEN
与日期一起使用,闭-开间隔提供更多优势,即使是日期也是如此。另请查看 Aaron 的文章,它还提到了为什么不应该将日期存储为字符串。以上是关于奇怪的窗口函数行为的主要内容,如果未能解决你的问题,请参考以下文章
使用 PostgreSQL 用户定义函数实现类似窗口函数的行为?