在Oracle 11g中的两个值之间选择行

时间:2018-08-26 14:12:22

标签: sql oracle oracle11g

这是我在很多地方看到的常见问题,但尚不知道是否可能。我正在尝试使用oracle sql开发工具以以下方式选择2到5之间的行。

此查询的结果是,应根据以下查询选择第三和第四查询

SELECT * FROM MyTable
WHERE ROWNUM > 2 AND ROWNUM < 5

但是它没有选择第三行和第四行,

然后我尝试了以下查询

SELECT * FROM MyTable
WHERE RN BETWEEN 2 AND 5

这在语法和程序上也正确,但是没有选择确切的列。

2 个答案:

答案 0 :(得分:5)

使用子查询:

SELECT t.*
FROM (SELECT t.*, ROWNUM as rn
      FROM MyTable t
     ) t
WHERE rn > 2 AND rn < 5;

请注意,表表示无序集。没有第一排或第二排。您应该有一个ORDER BY子句来指定顺序。

您的版本不起作用的原因是,当第一行放入结果集中时,rownum从1开始。如果未放入任何行,则该值永远不会增加。因此,它永远不会达到2或3。

我还应该注意,SQL中的between是包含在内的。因此,>=<=更合适。

编辑:

我应该注意到Oracle 12+支持FETCH / OFFSET

select t.*
from mytable t
offset 2                  -- start on the third row
fetch first 2 rows only   -- fetch two rows in total

在这种情况下,仍建议使用order by

答案 1 :(得分:3)

一些分析。

EMP表中的薪水(按$$$排序)如下:

SQL> select ename, sal
  2  from emp
  3  order by sal;

ENAME             SAL
---------- ----------
SMITH             800
JAMES             950   2   you want to return James ...
WARD             1250   3
MARTIN           1250   4
MILLER           1300   5   ... to Miller
TURNER           1500
ALLEN            1600
CLARK            2450
BLAKE            2850
JONES            2975
FORD             3000
KING             5000

12 rows selected.

SQL>

如果执行以下操作,将会获得所需的内容:

SQL> select ename, sal, rn
  2  from (select ename, sal, row_number() over (order by sal) rn
  3        from emp
  4       )
  5  where rn between 2 and 5;

ENAME             SAL         RN
---------- ---------- ----------
JAMES             950          2
WARD             1250          3
MARTIN           1250          4
MILLER           1300          5

SQL>

但是,正如您所看到的,沃德和马丁赚了同样的1250美元。那么,我们是否应该算出他们的薪水相同,是否将特纳列入名单?还有另外两个分析函数可以帮助您确定:RANKDENSE_RANK

SQL> select ename, sal,
  2    row_number() over (order by sal) rn,
  3    rank() over (order by sal) rnk,
  4    dense_rank() over (order by sal) drnk
  5  from emp
  6  order by sal;

ENAME             SAL         RN        RNK       DRNK
---------- ---------- ---------- ---------- ----------
SMITH             800          1          1          1
JAMES             950          2          2          2   2nd isn't questionable, but ...
WARD             1250          3          3          3
MARTIN           1250          4          3          3
MILLER           1300          5          5          4   ... which one is 5th? Miller (RN and RNK), ...
TURNER           1500          6          6          5   ... or Turner (DRNK column)?
ALLEN            1600          7          7          6
CLARK            2450          8          8          7
BLAKE            2850          9          9          8
JONES            2975         10         10          9
FORD             3000         11         11         10
KING             5000         12         12         11

12 rows selected.

SQL>

为公平起见,在这种情况下,DENSE_RANK可能是最佳选择:

SQL> select ename, sal, drnk
  2  from (select ename, sal, dense_rank() over (order by sal) drnk
  3        from emp
  4       )
  5  where drnk between 2 and 5;

ENAME             SAL       DRNK
---------- ---------- ----------
JAMES             950          2
WARD             1250          3
MARTIN           1250          3
MILLER           1300          4
TURNER           1500          5

SQL>

现在您有几种选择;选择最适合您的那个。