假设我有一个运动会结果数据库,其模式如下
DATE,NAME,FINISH_POS
我想做一个查询来选择运动员至少参加过三场比赛但没有获胜的所有行。例如使用以下样本数据
2013-06-22,Johnson,2
2013-06-21,Johnson,1
2013-06-20,Johnson,4
2013-06-19,Johnson,2
2013-06-18,Johnson,3
2013-06-17,Johnson,4
2013-06-16,Johnson,3
2013-06-15,Johnson,1
以下行:
2013-06-20,Johnson,4
2013-06-19,Johnson,2
将被匹配。我只设法从以下 stub 开始:
select date,name FROM table WHERE ...;
我一直在努力思考 where 子句,但我什至无法开始
最佳答案
我认为这可以更简单/更快:
SELECT day, place, athlete
FROM (
SELECT *, min(place) OVER (PARTITION BY athlete
ORDER BY day
ROWS 3 PRECEDING) AS best
FROM t
) sub
WHERE best > 1
使用聚合函数 min()
作为窗口函数获取最后三行加上当前行的最小位置。
由于在 best > 1
之后 应用了窗口函数,因此必须在下一个查询级别完成对“未获胜”( WHERE
) 的简单检查条款。所以你至少需要一个CTE子选择条件的窗口函数的结果。
关于 window function calls in the manual here 的详细信息.特别是:
If
frame_end
is omitted it defaults toCURRENT ROW
.
如果place
( finishing_pos
) 可以为 NULL,请改用它:
WHERE best IS DISTINCT FROM 1
min()
忽略 NULL
值,但如果框架中的所有行都是 NULL
, 结果是 NULL
.
不要使用类型名和保留字作为标识符,我用day
代替了为你的 date
.
假设每天最多有 1 场比赛,否则您必须定义如何处理时间线中的同行或使用 timestamp
而不是 date
.
@Craig已经提到了使这个速度更快的索引。
关于sql - 选择运动员在过去 3 项比赛中未获得第一名的成绩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17247725/