040908 R Oracle & SqlServer 's ORDER -->select top & where rownum <= 3

博客介绍了在MS SQLSERVER和ORACLE中取出表中按某字段排序的前N条记录的方法。MS SQLSERVER用TOP语法简单实现,而ORACLE没有TOP语法,需用ROWNUM结合子查询实现。还提及了取排序前M到N条记录的方法及不同数据库的处理差异。

MS SQLSERVERORACLE中取出表中按照某字段排序的前N条记录

 

这个题目看上去似乎那么简单, 两种数据库都提供ORDER BY 子句. 问题应该能够迎刃而解吧.

 

先试一下MS SQLSERVER是怎么做的:

     

use Northwind;

create table TestSort (ID integer);

insert into testSort values (3);

insert into testSort values (1);

insert into testSort values (4);

insert into testSort values (2);

select * from testSort;    

-----------------------------------------

ID         

-----------

3

1

4

2

(4 row(s) affected)

 

假设我们要取出按照ID排序的前三条记录:

    

select TOP 3 * from testSort order by ID ;       

-----------------------------------------

ID         

-----------

1

2

3

(3 row(s) affected) 

 

很简单,一句话就解决了.

 

再试一下ORACLE (这里用ORACLE9i)

SQL>  create table TestSort ( ID number);

Table created.

SQL> insert into testSort values (3);

1 row created.

SQL> insert into testSort values (1);

1 row created.

SQL> insert into testSort values (4);

1 row created.

SQL> insert into testSort values (2);

1 row created.

SQL> commit;

Commit complete.

SQL> select * from testSort;

ID

----------

         3

         1

         4

         2

 

ORACLE没有MS SQLSERVER中取前N条记录的TOP语法. 但是有ROWNUM可以用来完成类似功能.

 

SQL> select * from TestSort where rownum <= 3 order by ID;

ID

----------

         1

         3

         4

 

结果是不是有点出乎意料? 它并没有返回所要求的 1 , 2 , 3的结果 . ORACLE先根据rownum <=3的条件限制选取一个范围集合(3,1,4), 然后再在这个集合里进行排序.

ORDER BY 子句是在合适的记录被取出后才起作用.

原来如此, 那么在ORACLE中如何才能实现这个功能呢?

通常我们可以采用这种办法:

SQL> select * from (select * from TestSort order by ID) where rownum <=3;

        ID

----------

         1

         2

         3

 

    有点麻烦,不过也只能这样.

   

相同道理, 如果想从表中取出按照某字段排序前MN条记录

下面的ORACLE语句是最好的:

 

SQL> select ID from

     (

       select ID , rownum as con from

       (

        select ID  from TestSort order by ID

       )

       where rownum <= 3   /*N*/

     )

     where con >= 2;  /*M */

 

       

 

ID

----------

         2

         3

 

MS SQLSERVER中也可以用类似的思路解决此类问题.

 

当然你也可以用笨一点的办法, 比如用前N条记录的集合MINUSM-1条记录的集合得到

MN条记录集合. (有点象饶口令) , 不过MS SQLSERVER好象不支持MINUS之类的集合操作.

 

看来小小的一个排序取值问题还真不是那么简单呢 !

 

 

                                      Black_Snail

                                      Ligang1000@hotmail.com

 

                                      欢迎交流,转贴请保留以上信息

&lt;think&gt;好的,我现在需要帮用户将SQL Server的查询语句转换为Oracle语法。原来的查询是SELECT TOP 1 KSDM FROM MS_MZXX WHERE BRID = 16。首先,我得回忆一下这两个数据库在限制查询结果方面的区别。 SQL Server中,TOP子句用于指定返回的行数,比如TOP 1就是只取第一条记录。而Oracle不直接支持TOP关键字,它用的是ROWNUM这个伪列来实现类似的功能。所以,我需要将TOP 1替换成使用ROWNUM的方式。 一般来说,在Oracle中,如果要取第一条记录,可以在WHERE子句中加上ROWNUM = 1。不过,需要注意的是,ROWNUM是在数据检索之后应用的,所以如果有排序的需求,应该先排序再应用ROWNUM。但在这个例子里,用户只是要TOP 1,没有指定排序,所以可能默认是按照物理存储顺序或者某种默认排序来取第一条。 不过,用户原来的查询可能隐含了某种顺序,或者他们希望明确排序后再取第一条。这时候可能需要加上ORDER BY子句,然后在子查询中使用ROWNUM。例如,如果用户需要按照某个字段排序后的第一条记录,应该写成: SELECT KSDM FROM (SELECT KSDM FROM MS_MZXX WHERE BRID = 16 ORDER BY 某个字段) WHERE ROWNUM = 1; 但原查询中没有ORDER BY,所以可能不需要排序,直接取第一条。因此,最简单的转换可能是在WHERE子句后加上AND ROWNUM = 1,或者将ROWNUM条件放在外层查询。 不过,直接写成SELECT KSDM FROM MS_MZXX WHERE BRID = 16 AND ROWNUM = 1是否正确呢?是的,这会返回满足BRID=16条件的第一条记录,根据Oracle的执行计划,可能在没有ORDER BY的情况下,返回的是物理存储顺序中的第一条。 但有时候,为了确保正确性,尤其是当有多个符合条件的记录时,用户可能想要明确的排序,这时候就需要子查询和ORDER BY。如果用户不确定是否需要排序,可能需要进一步询问,但根据问题描述,用户只是要转换语法,所以可能不需要额外处理。 所以,最终的转换结果应该是: SELECT KSDM FROM MS_MZXX WHERE BRID = 16 AND ROWNUM = 1; 或者,如果用户希望保持与TOP 1完全相同的语义,即无论是否有排序,都取第一条,那么可能需要使用子查询: SELECT KSDM FROM (SELECT KSDM FROM MS_MZXX WHERE BRID = 16) WHERE ROWNUM = 1; 不过,根据Oracle的处理方式,这两种写法可能效果相同,但第一种更简洁。 另外,需要注意的是,Oracle中的ROWNUM是在数据筛选之后应用的,所以放在WHERE子句中是正确的。 总结,用户的问题是将TOP 1转换为Oracle语法,最直接的方式就是用ROWNUM = 1。&lt;/think&gt;### SQL Server到Oracle的语法转换 将SQL Server的`SELECT TOP 1`转换为Oracle语法时,需用Oracle的`ROWNUM`实现类似功能。以下是等效转换步骤: 1. **原始SQL Server语句** ```sql SELECT TOP 1 KSDM FROM MS_MZXX WHERE BRID = 16 ``` 2. **Oracle等效语法** ```sql SELECT KSDM FROM MS_MZXX WHERE BRID = 16 AND ROWNUM = 1 ``` - **`ROWNUM`的作用**:Oracle通过伪列`ROWNUM`限制返回行数,`ROWNUM = 1`表示仅取第一行[^1]。 - **执行顺序**:`ROWNUM`在数据筛选后生成,因此需直接在`WHERE`子句中添加条件[^2]。 3. **若需明确排序后取第一条** 如果原查询隐含排序逻辑(如依赖索引顺序),需显式添加`ORDER BY`并通过子查询实现: ```sql SELECT KSDM FROM ( SELECT KSDM FROM MS_MZXX WHERE BRID = 16 ORDER BY 某字段 -- 例如按时间排序 ) WHERE ROWNUM = 1 ``` ### 性能优化建议 - **索引优化**:为`BRID`字段添加索引可加速查询,避免全表扫描[^3]。 - **分页场景**:若需分页,可结合`ROWNUM`和子查询(如`WHERE ROWNUM &lt;= N`)。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值