【问题标题】:Oracle SQL - Select most recent occurrence of rowOracle SQL - 选择最近出现的行
【发布时间】:2018-06-12 07:05:51
【问题描述】:

这是我目前的情况:我有一系列相互构建的子查询。我有员工的工作是写日志。然后对这些日志进行审查和编辑,我只想提取最近的编辑(因为每个相应的编辑都连接在它之前的编辑之上。

因此,如果我在上午 10:00 编辑它,然后在上午 11:00 进行编辑,则上午 11:00 的编辑还将包含上午 10:00 的文本,但两个值都已存储。这就是我们的系统存储信息的方式……无法更改)。但是,如果我将这两个表连接在一起,它会提取给定日志的所有编辑。

我的问题是我有多个日志,并且只想为每个日志提取最新的 EDIT。我尝试了以下哪种方法有效,但它只提取了 OVERALL 最近的编辑,而不是 EACH 日志的最新编辑:

-- I have WITH and the other subqueries above...
sqEDITS AS
(
    SELECT
        Othertable.*, EDIT_TXT
    FROM
        Othertable
    LEFT JOIN 
        EDITS ON Othertable.LOG_NO = EDITS.EDIT_LOG_NO
    WHERE 
        EDIT_ACTIVITY_DT = (SELECT MAX(EDITS.EDIT_ACTIVITY_DT)
                            FROM Othertable, EDITS
                            WHERE Othertable.LOG_NO = EDITS.EDIT_LOG_NO) -- end where
) --end sqEDITS

在我的测试集中,有 35 个独特的日志,每个日志应该返回 35 个最近的编辑(如果存在的话)。

我的另一个问题是我试图提取的 TEXT 数据类型是 CLOB,这使得它很难使用。

任何建议将不胜感激。我肯定被难住了。谢谢!

【问题讨论】:

  • 验证您的专栏! (EDIT_ACTIVITY_DT 列属于哪个表?)
  • EDITS,所以完整的表将是 EDITS.EDIT_ACTIVITY_DT 我现在将进行这些更改。谢谢你的建议。
  • 将该条件从 WHERE 移至 ON。 (即只需将 WHERE 替换为 AND。)
  • 嗨,贾尔。那没有用

标签: sql oracle join greatest-n-per-group


【解决方案1】:

永远不要FROM 子句中使用逗号。学习使用正确、明确的JOIN 语法。

在您的情况下,问题在于子查询引用了两个表。我认为您打算使用相关子查询:

sqEDITS AS (
         SELECT Othertable.*, EDIT_TXT
         FROM Othertable LEFT JOIN
              EDITS
              ON Othertable.LOG_NO = EDITS.EDIT_LOG_NO
        WHERE EDIT_ACTIVITY_DT = 
              (SELECT MAX(EDITS.EDIT_ACTIVITY_DT)
               FROM EDITS
               WHERE Othertable.LOG_NO = EDITS.EDIT_LOG_NO
              ) -- end where
       ) --end sqEDITS

【讨论】:

  • 谢谢,戈登·林诺夫。我会试试这个,我会尽快回复你。
  • Gordon,看起来当我在尝试添加编辑文本之前查看我的所有日​​志时,我有 35 个正在测试的独特样本。然而,在运行这个之后,我有 51 个——所以我在某些地方确实有一些重复。
【解决方案2】:

您应该使用分析函数进行排名。

SELECT columna,columnb FROM (
  SELECT columna,columnb
  RANK() OVER (PARTITION BY columna ORDER BY (column of date ) DESC) AS  RNK   
       FROM  table 
) WHERE RNK=1

【讨论】:

  • 嗨,艾丁·奥兹古尔。非常感谢您的评论。我会在几分钟内尝试一下,然后回复您。
【解决方案3】:

你可以使用窗口函数:

SELECT othertable.*, edit_txt
FROM othertable -- Get logs (?)
LEFT JOIN ( -- Get most recent edit for each log
    SELECT edit_txt
    FROM (
        SELECT edit_txt
        FROM edits
        WHERE RANK() OVER(PARTITION BY edit_log_no ORDER BY edit_activity_dt DESC) = 1 -- For each log_no, only return most recent edit (based on edit_activity_dt value)
    ) edits
) edits ON othertable.log_no = edits.edit_log_no

让我知道这是否有效。

更新
这应该有效:

SELECT othertable.*, edit_txt
FROM othertable -- Get logs (?)
LEFT JOIN ( -- Get most recent edit for each log
    SELECT edit_txt, edit_log_no
    FROM (
      SELECT edit_txt, edit_log_no, RANK() OVER(PARTITION BY edit_log_no ORDER BY edit_activity_dt DESC) EditRank
      FROM edits
    ) src
    WHERE EditRank = 1
) edits ON othertable.log_no = edits.edit_log_no

您可以将“WHERE EditRank = 1”移动到 JOIN 条件并去掉子选择。不确定这是否会提高性能,但可读性会更容易。

【讨论】:

  • 谢谢,馄饨。感谢您的回复。你能解释一下什么是窗口函数吗?它有点像将我使用的 WITH...AS 子查询方法与排名分析函数结合起来,如下所述。我希望有一天能学到足够的知识来帮助像你一样的人!
  • 窗口函数类似于聚合函数(SUM、MIN、MAX、AVG)。不同之处在于它们允许您根据 PARTITION BY 表达式处理结果集中的行组。如果您不包含 PARTITION BY 表达式,则它们会返回整个行集的值。这有点枯燥,但请看一下这个 Oracle 特定的链接:oracle.com/technetwork/issue-archive/2013/13-mar/…。也可以搜索“窗口函数”
  • 啊,好的-谢谢!我只是尝试运行它,看起来配置我们的 DBMS 的人搞砸了它,它错误地告诉我这里不允许使用窗口类型的功能,所以看起来这条路已经关闭了 :( 谢谢你的尝试! :)
  • 你能想出任何方法来尝试实现这一目标吗?下面,Gordon 的方法运行没有问题,但不幸的是没有返回相同数量的行。在少数情况下,多次返回相同的日志。
  • 是的,给我一秒钟 :)
猜你喜欢
  • 2012-07-11
  • 2018-08-20
  • 1970-01-01
  • 1970-01-01
  • 2020-06-16
  • 2015-06-21
  • 2020-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多