小编典典

选择过去3项比赛中未获得第一名的终点

sql

假设我有一个运动会结果数据库,结构如下

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子句上,但是我什至无法开始


阅读 170

收藏
2021-04-14

共1个答案

小编典典

我认为这可以更简单/更快:

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的子选择条件才能满足窗口函数结果的条件。

手册中有关窗口函数调用的详细信息。特别是:

如果 frame_end 省略,则默认为CURRENT ROW

如果placefinishing_pos)可以为NULL,请改用以下方法:

WHERE  best IS DISTINCT FROM 1

min()忽略NULL值,但是如果框架中的所有行均为NULL,则结果为NULL

不要使用类型名称和保留字作为标识符,我会用day您代替date

假设每天最多进行1场比赛,否则您必须定义如何在时间轴上与同龄人打交道或使用timestamp代替date

@Craig已经提到了索引以使其快速。

2021-04-14