假设我有一个运动会结果数据库,结构如下
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
将被匹配。我只设法从以下存根开始:
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
- > SQLfiddle的
使用聚合函数min()作为窗口函数来获取最后三行加上当前行的最小位置。 然后best > 1必须在下一个查询级别对“ no win”()进行细微的检查,因为在子句 之后 应用了窗口函数WHERE。因此,您需要至少一个CTE的子选择条件才能满足窗口函数结果的条件。
min()
best > 1
WHERE
手册中有关窗口函数调用的详细信息。特别是:
如果 frame_end 省略,则默认为CURRENT ROW。
frame_end
CURRENT ROW
如果place(finishing_pos)可以为NULL,请改用以下方法:
place
finishing_pos
WHERE best IS DISTINCT FROM 1
min()忽略NULL值,但是如果框架中的所有行均为NULL,则结果为NULL。
NULL
不要使用类型名称和保留字作为标识符,我会用day您代替date。
day
date
假设每天最多进行1场比赛,否则您必须定义如何在时间轴上与同龄人打交道或使用timestamp代替date。
timestamp
@Craig已经提到了索引以使其快速。