几点…
除非您使用联接Made_Up_Of
和Season
过滤出行,否则不需要这些表。我把它们留在这里了;您可以根据需要将它们重新添加。
Mark Tickner是正确的,应该使用ANSI JOIN语法。关于它的好处(不是标准的)是,它将连接逻辑与要连接的表放在一起。一旦您习惯了它,我认为您会发现它更可取。
您真正想要的是pf.StartDate
每个函数的最大值PlayerID
,非常适合解析ROW_NUMBER()
函数。在PARTITION BY pi.PlayerID ORDER BY pf.StartDate DESC
将基本值分配1
给每个球员的最新数据排序的行。外部过滤出除具有1
排名的行以外的所有行。
您也可以使用RANK()
和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
或PDO
代替它们,因为它们可以保护您免受sql注入的侵害。这些MysqL
功能(已正式弃用)不会。
:有关的更多信息ROW_NUMBER
,非常感谢@AndriyM。
使用ROW_NUMBER
,如果玩家具有多个最近日期的行,则仅将其中一行分配为ROW_NUMBER = 1
,并且将或多或少地随机选择该行。这是一个示例,其中玩家的最近日期是2013年5月1日,并且该玩家具有该日期的三行:
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
请注意,只有 以上的行会被分配ROW_NUMBER = 1
,并且 它可以是任何人@H_301_79@ 。甲骨文将决定,而不是您。
如果不确定性是一个问题,请按其他列排序以获得明确的赢家。对于此示例,pi.MatchID
将使用最高值来确定“ true” 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
_寻找 _最高的@H_301_79@ 。事实证明,只有一行满足以下条件:
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