Oracle rownum返回错误的结果

时间:2015-01-22 17:59:15

标签: sql oracle

我正在尝试查询只返回表中的最新行。

最初我在查询中使用了max(id) 但是当我使用序列并且我的集合被聚集时,我不能依赖序列作为它的乱序。 所以我决定根据创建时间订购并使用rownum选择顶行。

我使用了像

这样的东西
SELECT  A.id
    FROM Table_A, Table_B B
    WHERE A.status = 'COMPLETED'
    AND B.name = 'some_name'
    AND A.id = B.id
    AND rownum = 1
    order by A.Creation_Time;

这有些怎么回事我说错了42145。 如果我删除了rownum condtn,则顶级记录是不同的,例如45343;

2 个答案:

答案 0 :(得分:8)

rownumorder by一起使用时,您需要使用子查询。这与whereorder by的评估顺序有关。所以,试试这个:

SELECT t.*
FROM (SELECT A.id
      FROM Table_A JOIN 
           Table_B B
           ON A.id = B.id
      WHERE A.status = 'COMPLETED' AND B.name = 'some_name'
      ORDER BY A.Creation_Time
     ) ab
WHERE rownum = 1;

我应该补充一点:Oracle 12支持fetch first 1 row only,这更方便:

  SELECT A.id
  FROM Table_A JOIN 
       Table_B B
       ON A.id = B.id
  WHERE A.status = 'COMPLETED' AND B.name = 'some_name'
  ORDER BY A.Creation_Time
  FETCH FIRST 1 ROW ONLY;

答案 1 :(得分:-1)

你有意这么做吗? (指定订购DESC)

SELECT  A.id
    FROM Table_A, Table_B B
    WHERE A.status = 'COMPLETED'
    AND B.name = 'some_name'
    AND A.id = B.id
    AND rownum = 1
    order by A.Creation_Time DESC;

编辑:显然指定订单DESC对您的查询至关重要。我不得不提升Gordon,因为他完全正确你需要限制排序后返回的行,所以他建议的方法是完美的。所以,对于那些阅读这篇文章的人来说,我想毫无疑问地确保在处理where子句之后但在排序或聚合之前(source)分配了rownum。

注意:和戈登的答案一样好,还有一个考虑因素可能会或可能不会在这里重要。看起来可能有重复的A.Creation_Time值,这可能会导致您看到非确定性行为,只要在执行该查询时可能返回哪些重复行。如果可能出现这个问题,Tom Kyte(与之前相同的链接)建议在order by子句中添加一些唯一的列值作为一个简单的闪避。例如:

SELECT t.id
FROM (SELECT *
      FROM (SELECT A.id, A.Creation_Time
            FROM Table_A A 
            JOIN Table_B B
            ON A.id = B.id
            WHERE A.status = 'COMPLETED' AND B.name = 'some_name'
           )
      ORDER BY Creation_Time, rowid DESC 
     ) t
WHERE rownum = 1;

其中ROWID是一个可用于此目的的唯一伪列。