2010-03-23 128 views
85

我在Oracle中有一个SQL语句的大问题。我想选择STORAGE_DB订购的不在其他选择语句列表中的TOP 10 Records。Oracle SELECT TOP 10条记录

这其中的所有记录正常工作:

SELECT DISTINCT 
    APP_ID, 
    NAME, 
    STORAGE_GB, 
    HISTORY_CREATED, 
    TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE 
    FROM HISTORY WHERE 
     STORAGE_GB IS NOT NULL AND 
     APP_ID NOT IN (SELECT APP_ID 
         FROM HISTORY 
         WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

但是,当我加入

AND ROWNUM <= 10 
ORDER BY STORAGE_GB DESC 

我得到某种“随机”记录。我认为是因为限制在订单之前已经到位。

有人有一个很好的解决方案吗?另一个问题:该查询是真的慢(10K +记录)

+0

可能的重复:http://stackoverflow.com/questions/2306744/oracle-sql-how-to-retrieve-highest-5-values-of-a-column – APC 2010-03-23 06:48:38

回答

142

你需要把在子查询当前的查询如下:

SELECT * FROM (
    SELECT DISTINCT 
    APP_ID, 
    NAME, 
    STORAGE_GB, 
    HISTORY_CREATED, 
    TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE 
    FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
     APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009') 
    ORDER BY STORAGE_GB DESC) 
WHERE ROWNUM <= 10 

甲骨文适用rownum的结果已经返回后。
您需要在返回结果后过滤结果,因此需要子查询。您还可以使用RANK()函数获取Top-N结果。

对于性能尝试使用NOT EXISTS代替NOT IN。有关更多信息,请参阅this

+0

NOT EXISTS在这种情况下不起作用(无效关系运算符)APP_ID NOT EXISTS(SELEC ...) – opHASnoNAME 2010-03-23 08:22:30

22

关于表现不佳的问题,有很多可能的事情,它应该是一个单独的问题。但是,这可能是一个问题,一个显而易见的事情:

WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

如果HISTORY_DATE真的是一个日期列,如果它有一个索引,然后这个重写将有更好的表现:

WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY') 

这是因为数据类型转换禁止使用B-Tree索引。

10

由于ROWNUM应用于ORDER BY之前,因此您会得到一个明显随机的集合。所以你的查询需要前10行并对它们进行排序。0,选择排名前十的工资,你应该在子查询中使用的解析函数,然后筛选:

select * from 
    (select empno, 
      ename, 
      sal, 
      row_number() over(order by sal desc nulls last) rnm 
    from emp) 
where rnm<=10 
11

如果您正在使用Oracle 12c中,你可以使用:

获取下一个N行只

SELECT DISTINCT 
    APP_ID, 
    NAME, 
    STORAGE_GB, 
    HISTORY_CREATED, 
    TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE 
    FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
     APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009') 
    ORDER BY STORAGE_GB DESC 
FETCH NEXT 10 ROWS ONLY 

更多信息:http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html

+1

简单而重要。 FETCH NEXT 10 ROWS ONLY – 2018-02-27 12:49:58

-4

你可以只需使用TOP条款

SELECT TOP 10 * FROM TABLE;

或者

SELECT列名(多个) FROM TABLE_NAME WHERE ROWNUM < =数目;

+1

不在oracle中SQL ... – Zafi 2017-07-12 08:33:42

2

尝试 SELECT * FROM users FETCH NEXT 10 ROWS ONLY;

+0

只适用于Oracle 12c及更高版本 – Volpato 2017-10-23 20:24:58