当前位置: 首页 > 面试题库 >

仅在Oracle中仅在一列上有所不同

暨成双
2023-03-14
问题内容

我想在下表中使用“ distinct”,但仅在“ PlayerID”列上使用。这是我目前所拥有的:

   MATCHID   PLAYERID     TEAMID MATCHDATE STARTDATE
---------- ---------- ---------- --------- ---------
        20          5          2 14-JAN-12 01-JUN-11
        20          5          4 14-JAN-12 01-JUN-10
        20          7          4 14-JAN-12 01-JUN-11
        20          7          2 14-JAN-12 01-JUN-10
        20         10          4 14-JAN-12 01-JUN-11
        20         11          2 14-JAN-12 01-JUN-10
        20         13          2 14-JAN-12 01-JUN-11
        20         16          4 14-JAN-12 01-JUN-10
        20         17          4 14-JAN-12 01-JUN-10
        20         18          4 14-JAN-12 01-JUN-10
        20         19          2 14-JAN-12 01-JUN-11

这就是我想要的,以便显示每个“ PlayerID”的最高“ StartDate”,而忽略下一行:

   MATCHID   PLAYERID     TEAMID MATCHDATE STARTDATE
---------- ---------- ---------- --------- ---------
        20          5          2 14-JAN-12 01-JUN-11
        20          7          4 14-JAN-12 01-JUN-11
        20         10          4 14-JAN-12 01-JUN-11
        20         11          2 14-JAN-12 01-JUN-10
        20         13          2 14-JAN-12 01-JUN-11
        20         16          4 14-JAN-12 01-JUN-10
        20         17          4 14-JAN-12 01-JUN-10
        20         18          4 14-JAN-12 01-JUN-10
        20         19          2 14-JAN-12 01-JUN-11

当前的SQL:

SELECT pi.MatchID, pi.PlayerID, t.TeamID, m.MatchDate, pf.StartDate
FROM Plays_In pi, Match m, Plays_A pa, Team t, Plays_For pf, Made_Up_Of muo, Season s
WHERE pi.MatchID = m.MatchID
AND m.MatchID = pa.MatchID
AND pa.TeamID = t.TeamID
AND pf.PlayerID = pi.PlayerID
AND pf.TeamID = t.TeamID
AND muo.MatchID = pi.MatchID
AND muo.SeasonID = s.SeasonID
AND pi.MatchID = '&match_id'
AND m.MatchDate >= pf.StartDate
ORDER BY pi.MatchID ASC, pi.PlayerID ASC, pf.StartDate DESC;

这是一个Oracle数据库。

提前致谢。


问题答案:

几点…

  • 除非您使用联接Made_Up_OfSeason过滤出行,否则不需要这些表。我把它们留在这里了;您可以根据需要将它们重新添加。

  • 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执行查询的功能。如果是这样,请研究mysqliPDO代替它们,因为它们可以保护您免受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,并且 它可以是任何人 。甲骨文将决定,而不是您。

如果不确定性是一个问题,请按其他列排序以获得明确的赢家。对于此示例,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_寻找 _最高的 。事实证明,只有一行满足以下条件:

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


 类似资料:
  • 问题内容: 如何仅在CSS中完成上标? 我有一个样式表,在其中我用一个上标字符标记了外部链接,但是我很难使字符正确对齐。 我目前所拥有的看起来像这样: 但这不起作用。 自然地,我只在允许HTML的情况下才使用-tag 。 问题答案: 您可以使用来做上标 vertical-align: super(加上相应的font-size减少项)。 但是,请务必在此处阅读其他答案,尤其是paulmurray和c

  • 当我编译react项目时,我有一个黄色的问题,但是下面的事情让我很不舒服 警告/节点_模块/React/cjs/React。发展js有多个模块,它们的名称只是大小写不同。在具有其他case语义的文件系统上编译时,这可能会导致意外行为。使用相等的外壳。比较这些模块标识符:*C:\cygwin64\home\waysolutions soft\curso\nodejs\react\node\u mod

  • 问题内容: 我有具有日期字段的表。当我运行查询时,我看到以下内容: 2009年1月10日22:10:39 如何只检索时间(IE:22:10:39) 问题答案: 您可以尝试以下方法: 编辑: 正如@steven指出的那样,要使用24小时样式

  • 我很久以前就问过这个问题.... 有没有办法在Gradle中列出任务依赖关系?

  • 那么,如何打印树中的所有路径呢。这里的条件是,我们不仅需要从根开始的路径或子树中的路径。 例如: 因此程序应该返回: 一种方法是在每个不同的节点对之间找到LCA,然后打印从LCA到两个节点的路径(在左子树中反转,在右子树中按顺序排列)。但是这里的复杂性是O(n3)。有更有效的解决方案吗?

  • 问题内容: 在终端我可以打电话给。现在,我想要一个c程序为我做这件事,像这样: 这将一切。但是,当我尝试: 我会收到一个运行时错误: ls:* /:没有这样的文件或目录 问题答案: 不幸的是,所有基于shell扩展的解决方案都受到最大命令行长度的限制。哪个有所不同(可以找出答案);在我的系统上,大约有2 MB。是的,许多人会争辩说它就足够了-一次比尔·盖茨就拥有640 KB的容量。 (在非共享文件