限制結果集行數


在進行數據檢索的時候有時候需要只檢索結果集中的部分行,比如說“檢索成績排前三名的學生”、“檢索工資水平排在第3位到第7位的員工信息”,這種功能被稱為“限制結果集行數”。在雖然主流的數據庫系統中都提供了限制結果集行數的方法,但是無論是語法還是使用方式都存在着很大的差異,即使是同一個數據庫系統的不同版本(比如

MSSQLServer2000和MSSQLServer2005)也存在着一定的差異。因此本節將按照數據庫系統來講解每種數據庫系統對限制結果集行數的特性支持。

  • MYSQL

MYSQL中提供了LIMIT關鍵字用來限制返回的結果集,LIMIT放在SELECT語句的最后位置,語法為“LIMIT 首行行號,要返回的結果集的最大數目”。比如下面的SQL語句將返回按照工資降序排列的從第二行開始(行號從0開始)的最多五條記錄:


SELECT * FROM T_Employee ORDER BY FSalary DESC LIMIT 2,5 

很顯然,下面的SQL語句將返回按照工資降序排列的前五條記錄:


SELECT * FROM T_Employee ORDER BY FSalary DESC LIMIT 0,5 
  • MSSQLServer2000

MSSQLServer2000中提供了TOP關鍵字用來返回結果集中的前N條記錄,其語法為“SELECT TOP 限制結果集數目字段列表SELECT語句其余部分”,比如下面的SQL語句用來檢索工資水平排在前五位(按照工資從高到低)的員工信息:


select top 5 * from T_Employee order by FSalary Desc 

MSSQLServer2000沒有直接提供返回提供“檢索從第5行開始的10條數據”、“檢索第五行至第十二行的數據”等這樣的取區間范圍的功能,不過可以采用其他方法來變通實現,最常使用的方法就是用子查詢9,比如要實現檢索按照工資從高到低排序檢索從第六名開始一共三個人的信息,那么就可以首先將前五名的主鍵取出來,在檢索的時候檢索排除了這五名員工的前三個人,SQL如下:


SELECT top 3 * FROM T_Employee WHERE FNumber NOT IN(SELECT TOP 5 FNumber FROM T_Employee ORDER BY FSalary DESC) ORDER BY FSalary DESC 
  • MSSQLServer2005

MSSQLServer2005兼容幾乎所有的MSSQLServer2000的語法,所以可以使用上個小節提到的方式來在MSSQLServer2005中實現限制結果集行數,不過MSSQLServer2005提供了新的特性來幫助更好的限制結果集行數的功能,這個新特性就是窗口函數ROW_NUMBER()。

ROW_NUMBER()函數可以計算每一行數據在結果集中的行號(從1開始計數),其使用語法如下:

ROW_NUMBER OVER(排序規則)

比如我們執行下面的SQL語句:


SELECT ROW_NUMBER() OVER(ORDER BY FSalary),FNumber,FName,FSalary,FAge FROM T_Employee 

可以看到第一列中的數據就是通過ROW_NUMBER()計算出來的行號。有的開發人員想使用如下的方式來實現返回第3行到第5行的數據(按照工資降序):


SELECT ROW_NUMBER() OVER(ORDER BY FSalary DESC),FNumber,FName,FSalary,FAge FROM T_Employee WHERE (ROW_NUMBER() OVER(ORDER BY FSalary DESC))>=3 AND (ROW_NUMBER() OVER(ORDER BY FSalary DESC))<=5 

但是在運行的時候數據庫系統會報出下面的錯誤信息:

開窗函數只能出現在SELECT 或ORDER BY 子句中。

也就是說ROW_NUMBER()不能用在WHERE語句中。我們可以用子查詢來解決這個問題,下面

的SQL語句用來返回第3行到第5行的數據:


SELECT * FROM(SELECT ROW_NUMBER() OVER(ORDER BY FSalary DESC) AS rownum,FNumber,FName,FSalary,FAge FROM T_Employee) AS a WHERE a.rownum>=3 AND a.rownum<=5 
  • Oracle

Oracle中支持窗口函數ROW_NUMBER(),其用法和MSSQLServer2005中相同,比如我們

執行下面的SQL語句:


SELECT * FROM(SELECT ROW_NUMBER() OVER(ORDER BY FSalary DESC) row_num,FNumber,FName,FSalary,FAge FROM T_Employee) a WHERE a.row_num>=3 AND a.row_num<=5 

注意:rownum在Oracle中為保留字,所以這里將MSSQLServer2005中用到的rownum替換為row_num;Oracle中定義表別名的時候不能使用AS關鍵字,所以這里也去掉了AS。

Oracle支持標准的函數ROW_NUMBER(),不過Oracle中提供了更方便的特性用來計算行號,也就在Oracle中可以無需自行計算行號,Oracle為每個結果集都增加了一個默認的表示行號的列,這個列的名稱為rownum。比如我們執行下面的SQL語句:


SELECT rownum,FNumber,FName,FSalary,FAge FROM T_Employee 

使用rownum我們可以很輕松的取得結果集中前N條的數據行,比如我們執行下面的SQL語句可以得到按工資從高到底排序的前6名員工的信息:


SELECT * FROM T_Employee WHERE rownum<=6 ORDER BY FSalary Desc 

看到這里,您可能認為下面的SQL就可以非常容易的實現“按照工資從高到低的順序取出第三個到第五個員工信息”的功能了:


SELECT rownum,FNumber,FName,FSalary,FAge FROM T_Employee WHERE rownum BETWEEN 3 AND 5 ORDER BY FSalary DESC 

檢索結果為空!!!這非常出乎我們的意料。讓我們來回顧一下rownum的含義:rownum為結果集中每一行的行號(從1開始計數)。對於下面的SQL:


SELECT * FROM T_Employee WHERE rownum<=6 ORDER BY FSalary Desc 

當進行檢索的時候,對於第一條數據,其rownum為1,因為符合“WHERE rownum<=6”所以被放到了檢索結果中;當檢索到第二條數據的時候,其rownum為2,因為符合“WHERE

rownum<=6”所以被放到了檢索結果中……依次類推,直到第七行。所以這句SQL語句能夠實現“按照工資從高到低的順序取出第三個到第五個員工信息”的功能。而對於這句SQL語句:


SELECT rownum,FNumber,FName,FSalary,FAge FROM T_Employee WHERE rownum BETWEEN 3 AND 5 ORDER BY FSalary DESC 

當進行檢索的時候,對於第一條數據,其rownum為1,因為不符合“WHERE rownum BETWEEN 3 AND 5”,所以沒有被放到了檢索結果中;當檢索到第二條數據的時候,因為第一條數據沒有放到結果集中,所以第二條數據的rownum仍然為1,而不是我們想像的2,所以因為不符合“WHERE rownum<=6”,沒有被放到了檢索結果中;當檢索到第三條數據的時候,因為第一、二條數據沒有放到結果集中,所以第三條數據的rownum仍然為1,而不是我們想像的3,所以因為不符合“WHERE rownum<=6”,沒有被放到了檢索結果中……依此類推,這樣所有的數據行都沒有被放到結果集中。

因此如果要使用rownum來實現“按照工資從高到低的順序取出第三個到第五個員工信息”的功能,就必須借助於窗口函數ROW_NUMBER()。

  • DB2

DB2中支持窗口函數ROW_NUMBER(),其用法和MSSQLServer2005以及Oracle中相同,

比如我們執行下面的SQL語句:


SELECT * FROM(SELECT ROW_NUMBER() OVER(ORDER BY FSalary DESC) row_num,FNumber,FName,FSalary,FAge FROM T_Employee) a WHERE a.row_num>=3 AND a.row_num<=5 

除此之外,DB2還提供了FETCH關鍵字用來提取結果集的前N行,其語法為“FETCH FIRST 條數ROWS ONLY”,比如我們執行下面的SQL語句可以得到按工資從高到底排序的前6名員工的信息:


SELECT * FROM T_Employee ORDER BY FSalary Desc FETCH FIRST 6 ROWS ONLY 

需要注意的是FETCH子句要放到ORDER BY語句的后面DB2沒有直接提供返回提供“檢索從第5行開始的10條數據”、“檢索第五行至第十二行的數據”等這樣的取區間范圍的功能,不過可以采用其他方法來變通實現,最常使用的方法就是用子查詢,比如要實現檢索按照工資從高到低排序檢索從第六名開始一共三個人的信息,那么就可以首先將前五名的主鍵取出來,在檢索的時候檢索排除了這五名員工的前三個人,SQL如下:


SELECT * FROM T_Employee WHERE FNumber NOT IN(SELECT FNumber FROM T_Employee ORDER BY FSalary DESC FETCH FIRST 5 ROWS ONLY) ORDER BY FSalary DESC FETCH FIRST 3 ROWS ONLY


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM