我正在尝试通过以下查询返回每个PlayedTo
的两个最低PlayerID
结果。
select
x1.PlayerID, x1.RoundID, x1.PlayedTo
from P_7to8Calcs as x1
where
(
select count(*)
from P_7to8Calcs as x2
where x2.PlayerID = x1.PlayerID
and x2.PlayedTo <= x1.PlayedTo
) <3
order by PlayerID, PlayedTo, RoundID;
不幸的是,当其中一个得分最低时,它不会返回结果。数据集和代码的副本位于http://sqlfiddle.com/#!3/4a9fc/13。
PlayerID
47只返回了一个结果,因为有两个不同的RoundID
被绑定为第二个最低PlayedTo
。对于我想要计算的内容,它返回这两个中的哪一个并不重要,因为我只需要知道数字是什么,但是对于报告我理想地需要知道具有最新日期的那个。
查询的另一个小问题是运行所花费的时间。在Access中大约需要2分钟来运行83条记录,但是当数据库完全启动并运行时,它需要在大约1000条记录上运行。
非常感谢任何帮助。
答案 0 :(得分:2)
通过在内部排序中添加DatePlayed
来解决这个问题(你想要的是最新日期的那个):
select
x1.PlayerID, x1.RoundID
, x1.PlayedTo
from P_7to8Calcs as x1
where
(
select count(*)
from P_7to8Calcs as x2
where x2.PlayerID = x1.PlayerID
and (x2.PlayedTo < x1.PlayedTo
or x2.PlayedTo = x1.PlayedTo
and x2.DatePlayed >= x1.DatePlayed
)
) <3
order by PlayerID, PlayedTo, RoundID;
对于性能,创建支持连接条件的索引。类似的东西:
create index P_7to8Calcs__PlayerID_RoundID on P_7to8Calcs(PlayerId, PlayedTo);
注意:我使用了你的SQLFiddle,因为我没有这里的Acess。
编辑:如果索引没有足够提高性能,您可能希望使用窗口函数尝试以下查询(这避免了嵌套的子查询)。它适用于您的SQLFiddle,但我不确定Access是否支持它。
select x1.PlayerID, x1.RoundID, x1.PlayedTo
from (
select PlayerID, RoundID, PlayedTo
, RANK() OVER (PARTITION BY PlayerId ORDER BY PlayedTo, DatePlayed DESC) AS Rank
from P_7to8Calcs
) as x1
where x1.RANK < 3
order by PlayerID, PlayedTo, RoundID;
有关文档,请参阅OVER clause和Ranking Functions。