几点...
除非你使用连接Made_Up_Of
and Season
要过滤掉行,您不需要这些表。我把它们留在这里了;如果需要,您可以将它们添加回来。
Mark Tickner 是正确的,您应该使用 ANSI JOIN 语法。它的好处(除了标准之外)是它将连接逻辑与要连接的表放在一起。一旦你习惯了它,我想你会发现它更好。
你真正追求的是最大化pf.StartDate
对于每个PlayerID
,这非常适合分析ROW_NUMBER()
功能。这PARTITION BY pi.PlayerID ORDER BY pf.StartDate DESC
基本上会赋值1
到每个玩家最近排序日期的行。外部过滤掉除带有以下内容的行之外的所有行1
排行。
您还可以使用以下方式指定排名RANK()
and DENSE_RANK()
分析函数,但如果某个玩家最近的日期有平局,那么所有平局日期将排名第一,您将获得该玩家的多行。在这种情况下,您只需要每个玩家一行,请使用ROW_NUMBER()
反而。
把它们放在一起,你会得到这个:
SELECT MatchID, PlayerID, TeamID, MatchDte, StartDate FROM (
SELECT
pi.MatchID,
pi.PlayerID,
t.TeamID,
m.MatchDate,
pf.StartDate,
ROW_NUMBER() OVER (PARTITION BY pi.PlayerID ORDER BY pf.StartDate DESC) AS StartDateRank
FROM Plays_In pi
INNER JOIN Match m ON pi.MatchID = m.MatchID
INNER JOIN Plays_A pa ON m.MatchID = pa.MatchID
INNER JOIN Team t ON pa.TeamID = t.TeamID
INNER JOIN Plays_For pf ON pf.PlayerID = pi.PlayerID AND pf.TeamID = t.TeamID
WHERE pi.MatchID = '&match_id'
AND m.MatchDate >= pf.StartDate
)
WHERE StartDateRank = 1
ORDER BY MatchID, PlayerID
最后一点:基于WHERE pi.MatchID = '&match_id'
看起来您可能正在使用 PHP 作为前端,并且mysql
函数来进行查询。如果是这样,请查看mysqli
or PDO
相反,因为它们会保护您免受 SQL 注入。这mysql
函数(已被正式弃用)不会。
Addendum:更多关于ROW_NUMBER
,非常感谢@AndriyM。
With ROW_NUMBER
,如果一名玩家有多于一行具有最新日期,则只有其中一行将被分配为ROW_NUMBER = 1
,并且该行将或多或少地随机选取。下面是一个示例,其中玩家的最近日期是 5/1/2013,并且该玩家有三行包含此日期:
pi.MatchID pi.PlayerID pf.StartDate
---------- ----------- ------------
100 1000 05/01/2013 <-- could be ROW_NUMBER = 1
101 1000 04/29/2013
105 1000 05/01/2013 <-- could be ROW_NUMBER = 1
102 1000 05/01/2013 <-- could be ROW_NUMBER = 1
107 1000 04/18/2013
请注意,仅one上面的行将被分配ROW_NUMBER = 1
, and 它可以是其中任何一个。 Oracle 将决定,而不是您。
如果这种不确定性是一个问题,请按附加列排序以获得明显的获胜者。对于此示例,最高pi.MatchID
将用于确定“真实”ROW_NUMBER = 1
:
-- replace `ROW_NUMBER...` in the query above with this:
ROW_NUMBER() OVER (
PARTITION BY pi.PlayerID
ORDER BY pf.StartDate DESC, pi.MatchID DESC) AS StartDateRank
现在如果有最高的平局pf.StartDate
, Oracle 寻找最高的pi.MatchID
在具有最高值的行子集中pf.StartDate
。事实证明,只有一行满足这个条件:
pi.MatchID pi.PlayerID pf.StartDate
---------- ----------- ------------
100 1000 05/01/2013
101 1000 04/29/2013
105 1000 05/01/2013 <-- is ROW_NUMBER = 1: highest MatchID for
-- most recent StartDate (5/1/2013)
102 1000 05/01/2013
107 1000 04/18/2013 <-- not considered: has the highest MatchID but isn't
-- in the subset with the most recent StartDate