Oracle SQL - 选择最近出现的行

时间:2018-01-02 15:07:10

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

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

因此,如果我在上午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,这使得它很难使用。

任何建议都将不胜感激。我肯定难过。谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用窗口功能:

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

你可以移动&#34; WHERE EditRank = 1&#34;到JOIN条件并摆脱子选择。不确定这是否会提高性能,但可读性会更容易。

答案 1 :(得分:0)

从不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

答案 2 :(得分:0)

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

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