Oracle SQL篇(三)Oracle ROWNUM 與TOP N分析

?

??
首先我們來看一下ROWNUM:
含義解釋:
1、rownum是oracle為從查詢返回的行的編號,返回的第一行分配的是1,第二行是2,依此類推。這是一個偽列,可以用于限制查詢返回的總行數。
2、rownum不能以任何基表的名稱作為前綴。

對于ROWNUM來說,通常我們可以使用的比較符是<和<=,不能單獨的使用=、>、>=等比較運算符,其實我們可以這樣簡單的 理解,oracle是找到第一條的記錄添加序號1之后,才可以知道誰是第二條記錄,然后添加序號2,以此類推。所以對于等于來說,是可以有例外的,就是 rownum=1。

我們來看幾個簡單的演示:
?
scott@DB01> create table demo as select demono,ename,sal,comm,deptno from demo;
Table created.
scott@DB01> select rownum,t.* from demo t;

??? ROWNUM????? demoNO ENAME???????????? SAL?????? COMM???? DEPTNO
---------- ---------- ---------- ---------- ---------- ----------
???????? 1?????? 7369 SMITH???????????? 800??????????????????? 20
???????? 2?????? 7499 ALLEN??????????? 1600??????? 300???????? 30
???????? 3?????? 7521 WARD???????????? 1250??????? 500???????? 30
???????? 4?????? 7566 JONES??????????? 2975??????????????????? 20
???????? 5?????? 7654 MARTIN?????????? 1250?????? 1400???????? 30
???????? 6?????? 7698 BLAKE??????????? 2850??????????????????? 30
???????? 7?????? 7782 CLARK??????????? 2450??????????????????? 10
???????? 8?????? 7788 SCOTT??????????? 3000??????????????????? 20
???????? 9?????? 7839 KING???????????? 5000??????????????????? 10
??????? 10?????? 7844 TURNER?????????? 1500????????? 0???????? 30
??????? 11?????? 7876 ADAMS??????????? 1100??????????????????? 20
??????? 12?????? 7900 JAMES???????????? 950??????????????????? 30
??????? 13?????? 7902 FORD???????????? 3000??????????????????? 20
??????? 14?????? 7934 MILLER?????????? 1300??????????????????? 10

14 rows selected.

scott@DB01> select rownum,demono,ename,sal from demo where rownum<=3;

??? ROWNUM????? demoNO ENAME???????????? SAL
---------- ---------- ---------- ----------
???????? 1?????? 7369 SMITH???????????? 800
???????? 2?????? 7499 ALLEN??????????? 1600
???????? 3?????? 7521 WARD???????????? 1250

scott@DB01> select rownum,demono,ename,sal from demo where rownum<3;

??? ROWNUM????? demoNO ENAME???????????? SAL
---------- ---------- ---------- ----------
???????? 1?????? 7369 SMITH???????????? 800
???????? 2?????? 7499 ALLEN??????????? 1600

scott@DB01> select rownum,demono,ename,sal from demo where rownum=1;

??? ROWNUM????? demoNO ENAME???????????? SAL
---------- ---------- ---------- ----------
???????? 1?????? 7369 SMITH???????????? 800

scott@DB01> select rownum,demono,ename,sal from demo where rownum=3;

no rows selected

scott@DB01> select rownum,demono,ename,sal from demo where rownum>3;

no rows selected

如果我們想要查詢結果集中的某一段范圍的記錄,比如5-10條的記錄,該如何查詢呢?很多開發人員把這樣的需求稱為分頁
scott@DB01> select rownum,demono,ename,sal from demo where rownum between 5 and 10;
no rows selected

上面是一個錯誤的例子,我們來看正確的寫法,這里我們使用到了集合運算符minus(減法運算)
scott@DB01> select rownum,demono,ename,sal from demo where rownum<=10
? 2???????? minus
? 3???????? select rownum,demono,ename,sal from demo where rownum<=4;

??? ROWNUM????? demoNO ENAME???????????? SAL
---------- ---------- ---------- ----------
???????? 5?????? 7654 MARTIN?????????? 1250
???????? 6?????? 7698 BLAKE??????????? 2850
???????? 7?????? 7782 CLARK??????????? 2450
???????? 8?????? 7788 SCOTT??????????? 3000
???????? 9?????? 7839 KING???????????? 5000
??????? 10?????? 7844 TURNER?????????? 1500

6 rows selected.

如果我們有這樣一個需求,找到員工demo表中,薪水最高的前三名,如何來實現呢?在sql server中有標準的top n分析語句,不過不要放到oracle里來使用,不同的數據庫還是有區別的。當然了,也許你會認為這個問題有歧義,是前三個人呢?還是薪水排在最高3位的人?因為薪水有可能是相同的,在這里我們就找前三個人,看下面的語句:

scott@DB01> select rownum,demono,ename,sal
???????? 2> from demo
???????? 3> where rownum<=3
???????? 4> order by sal desc;

??? ROWNUM????? demoNO ENAME???????????? SAL
---------- ---------- ---------- ----------
???????? 2?????? 7499 ALLEN??????????? 1600
???????? 3?????? 7521 WARD???????????? 1250
???????? 1?????? 7369 SMITH???????????? 800

這個語句從表面上來看好像是正確的,從demo表里查詢數據,排序,最后利用rownum返回前三個人,但是我們看語句的執行結果顯然是不正確的。對于oracle的語句,我們在執行的時候遵循top-down的順序,或者我們可以說,語句按照順序來執行。

當然也有個別例外:
scott@DB01> select deptno,sum(sal) from demo
? 2???????? group by deptno
? 3???????? having sum(sal)>=10000;

??? DEPTNO?? SUM(SAL)
---------- ----------
??????? 20????? 10875

scott@DB01> select deptno,sum(sal) from demo
? 2???????? having sum(sal)>=10000
? 3???????? group by deptno;

??? DEPTNO?? SUM(SAL)
---------- ----------
??????? 20????? 10875

對于前面排名的語句當然是有問題的。當第2行語句執行后,拿到表中所有的數據,第3行語句緊接著執行,就把最前面的三條記錄取出來了(rownum是對查詢結果添加序號),這個時候,再做排序,當然拿到的就是對前面三條記錄排序的結果,如上所示。

正確的思路應該是,先做排序,再做條件篩選,也就是4行子句要在3行之前運行,如何來實現呢?在這里oracle借助了子查詢,用oracle的標準表述叫做內聯視圖(inline view),當然整個的sql就是oracle的top N分析語句的寫法,我們來看例子:

scott@DB01>? select rownum rank,t.*
? 2????????? from (select demono,ename,sal from demo order by sal desc) t
? 3????????? where rownum<=3;

????? RANK????? demoNO ENAME???????????? SAL
---------- ---------- ---------- ----------
???????? 1?????? 7839 KING???????????? 5000
???????? 2?????? 7788 SCOTT??????????? 3000
???????? 3?????? 7902 FORD???????????? 3000

在這里,oracle其實對內部子查詢做了優化處理,我們通常認為,簡單子查詢是內層查詢先執行,然后傳遞結果給外層查詢,然后外層查詢再執行。
但是對于這個例子,如果demo表數據量很大的話,那么內層排序需要花的時間就會非常多。而實際上呢,oracle會知道外層查詢需要的記錄數,如本例中是3,
oracle在對內層查詢排序時,并不是對demo表中的14條記錄做完全的排序,根據算法,他只要找到sal最高的3條就可以了,其余的11條記錄是沒必要排序的,這就大大的節省了語句的執行時間。

如果想要得到排序后的某段數據,我們可以通過嵌套的方法來實現:
scott@DB01> select t1.*?????? ?
? 2???????? from?? (select rownum rank,t.* from (select demono,ename,sal from demo order by sal desc) t) t1
? 3???????? where rank>=3 and rank<=7;

????? RANK????? demoNO ENAME???????????? SAL
---------- ---------- ---------- ----------
???????? 3?????? 7788 SCOTT??????????? 3000
???????? 4?????? 7566 JONES??????????? 2975
???????? 5?????? 7698 BLAKE??????????? 2850
???????? 6?????? 7782 CLARK??????????? 2450
???????? 7?????? 7499 ALLEN??????????? 1600
?

注:在前面兩個例子中,我們使用到了oracle的top N分析,不過都是對整張表,或者整個結果集來說的。其實oracle 對于類似的操作,提供了一套函數,我們稱之為分析函數,分析函數對于數據做統計和分析是非常有幫助的,我們在下面只是舉一個簡單的小例子,如果你感興趣可以看看

scott@DB01> select * from demo;
???? demoNO ENAME???????????? SAL?????? COMM???? DEPTNO
---------- ---------- ---------- ---------- ----------
????? 7369 SMITH???????????? 800??????????????????? 20
????? 7499 ALLEN??????????? 1600??????? 300???????? 30
????? 7521 WARD???????????? 1250??????? 500???????? 30
????? 7566 JONES??????????? 2975??????????????????? 20
????? 7654 MARTIN?????????? 1250?????? 1400???????? 30
????? 7698 BLAKE??????????? 2850??????????????????? 30
????? 7782 CLARK??????????? 2450??????????????????? 10
????? 7788 SCOTT??????????? 3000??????????????????? 20
????? 7839 KING???????????? 5000??????????????????? 10
????? 7844 TURNER?????????? 1500????????? 0???????? 30
????? 7876 ADAMS??????????? 1100??????????????????? 20
????? 7900 JAMES???????????? 950??????????????????? 30
????? 7902 FORD???????????? 3000??????????????????? 20
????? 7934 MILLER?????????? 1300??????????????????? 10

14 rows selected.

scott@DB01> break on deptno skip 1
scott@DB01> select *
? 2? from (select deptno,
? 3??????????????? ename,
? 4??????????????? sal,
? 5??????????????? dense_rank() over(partition by deptno order by sal desc) dr
? 6??????? from demo
? 7????????? )
? 8? where dr<=3
? 9? order by deptno;

??? DEPTNO ENAME???????????? SAL???????? DR
---------- ---------- ---------- ----------
??????? 10 KING???????????? 5000????????? 1
?????????? CLARK??????????? 2450????????? 2
?????????? MILLER?????????? 1300????????? 3

??????? 20 SCOTT??????????? 3000????????? 1
?????????? FORD???????????? 3000????????? 1
?????????? JONES??????????? 2975????????? 2
?????????? ADAMS??????????? 1100????????? 3

??????? 30 BLAKE??????????? 2850????????? 1
?????????? ALLEN??????????? 1600????????? 2
?????????? TURNER?????????? 1500????????? 3


10 rows selected.

scott@DB01> select * from (
? 2????????????????? select deptno,
? 3???????????????????????? ename,
? 4???????????????????????? sal,
? 5???????????????????????? row_number() over(partition by deptno order by sal desc) dr
? 6?????????????????? from demo
? 7???????????????? )
? 8? where dr<=3
? 9? order by deptno;

??? DEPTNO ENAME???????????? SAL???????? DR
---------- ---------- ---------- ----------
??????? 10 KING???????????? 5000????????? 1
?????????? CLARK??????????? 2450????????? 2
?????????? MILLER?????????? 1300????????? 3

??????? 20 SCOTT??????????? 3000????????? 1
?????????? FORD???????????? 3000????????? 2
?????????? JONES??????????? 2975????????? 3

??????? 30 BLAKE??????????? 2850????????? 1
?????????? ALLEN??????????? 1600????????? 2
?????????? TURNER?????????? 1500????????? 3

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/260967.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260967.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260967.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++ Primer 第10章 pair類型

//10.2.cpp //至少使用三種方法創建pair對象。 //編寫三個版本的程序&#xff0c;分別采用不同的方法來創建pair對象 //方法1&#xff1a;在定義pair對象時提供初始化式來創建pair對象#include<iostream> #include<vector> #include<utility> #include<st…

計算機對口升學可以報考的學校,對口升學可以報考的學校都在這里,趕快來收藏吧...

對口升學指對口高考&#xff0c;在平常又叫對口單招&#xff0c;對口升學&#xff0c;是從中等職業學校畢業生招生&#xff0c;強調中等職業學校畢業生對口升高職的專業技能考試&#xff0c;以專業技能成績為主要錄取依據的招生辦法。報名條件具有正式學籍的中等職業學校畢業生…

Visual Studio 常用快捷鍵 (二)

想不到上一篇 【Visual Studio 常用快捷鍵】 受這么多人的歡迎。看來大家對Visual Studio的用法非常感興趣。 接下來我準備寫一個 “Visual Studio使用技巧 ” 一個系列的博客。 希望對大家有所幫助 本篇繼續介紹幾個常用的快捷鍵 閱讀目錄 按兩下Tab鍵回退到光標的上一次位置…

js 兼容event.target

function getEventTarget(e){ewindow.event||e;return e.srcElement||e.target; }轉載于:https://www.cnblogs.com/manong13/archive/2012/02/23/2364443.html

企業郵箱收發信息服務器怎么設置,網易閃電郵企業郵箱收發設置教程(IMAP)...

網易閃電郵企業郵箱收發設置教程(IMAP)發表時間 2019-05-30人氣 73(1)啟動閃電郵后&#xff0c;點擊“郵箱---新建郵箱賬戶”菜單&#xff0c;如下圖&#xff1a;(2)輸入“郵箱地址和密碼”&#xff0c;點擊下拉箭頭繼續設置&#xff0c;設置完成后點擊下一步&#xff0c;如下圖…

訂餐系統之Excel批量導入

批量導入現在基本已經成為各類系統的標配了&#xff0c;當前&#xff0c;我們訂餐系統也不例外&#xff0c;什么商家呀、商品呀、優惠碼之類的&#xff0c;都少不了。畢竟嘛&#xff0c;對非開發人員來說&#xff0c;看到Excel肯定比看到很多管理系統還是要親切很多的。這里&am…

需要忽略的一些信號

程序往往會因為收到一些信號導致退出&#xff0c;但很多時候并不是我們想要的&#xff0c;比如往一個已經關閉的socket連接發送數據就會受到SIGPIPE,此信號默認會退出程序&#xff0c;但其實大部分時候我們并不想這么做&#xff0c;所以需要忽略一些信號。常見的有 SIGPIPE SIG…

獲取網頁中選中的文字

獲取頁面中選中的文字 //獲取頁面中選中的文字 function getSelectedText(){if(window.getSelection){ //FFreturn window.getSelection().toString();}else{ //IEreturn document.selection.createRange().text;} }設置或獲取輸入框的選中文字 //設置文字選中 function setSe…

云服務器和獨享虛擬主機的區別,獨享虛擬主機和云服務器的幾大區別

獨享虛擬主機和云服務器的幾大區別發布時間&#xff1a;2020-10-15 19:05:51來源&#xff1a;億速云閱讀&#xff1a;99作者&#xff1a;Leah欄目&#xff1a;云計算今天就跟大家聊聊有關獨享虛擬主機和云服務器的幾大區別&#xff0c;可能很多人都不太了解&#xff0c;為了讓大…

oracle數據庫之數據導入問題

2019獨角獸企業重金招聘Python工程師標準>>> 在oracle數據庫中建立好數據庫以后&#xff0c;需要使用PLSQL進行用戶創建&#xff0c;打開PLSQL&#xff0c;使用時需要使用最高權限進入PLSQL。如下圖&#xff1a; 不需要使用用戶名和密碼&#xff0c;進入數據庫操作。…

轉向ARC的說明

轉自hherima的博客原文&#xff1a;Transitioning to ARC Release Notes&#xff08;蘋果官方文檔&#xff09; ARC是一個編譯器特征&#xff0c;它提供了對OC對象自動管理內存。ARC讓開發者專注于感興趣的代碼和對象的關系&#xff0c;而不用考慮對象的retain和release。 概要…

ubuntu11.10 samba服務器配置

安裝samba可以實現linux下文件和window共享&#xff0c;這樣window下就可以操作linux的文件了。 1、關閉LINUX防火墻 sudo ufw disable 注&#xff1a;ufw是linux下的防火墻操作命令&#xff0c;相關的操作可以查看命令幫助 2、先卸載samba-common sudo ap…

win服務器創建文件夾命令,Win10系統如利用命令提示符或WSL創建任意大小空白文件...

要測試網盤或服務器的上傳&#xff0c;下載速度&#xff0c;需要指定大小的文件用來測試。創建的空白文件雖然沒有任何內容&#xff0c;但是有大小&#xff0c;可以用來測試實際傳輸速度、覆蓋已刪除數據等用途。這篇文章是本站教大家在Win10中用命令或WSL創建任意大小空白文件…

計算UILabel帶行間距的行高

為什么80%的碼農都做不了架構師&#xff1f;>>> //設置lab的行間距 NSMutableAttributedString *attributedString [[NSMutableAttributedString alloc] initWithString:_doubletStr]; NSMutableParagraphStyle *paragraphStyle [[NSMutableParagraphStyle alloc…

FORM級別和數據庫級別的Trace

&#xfeff;&#xfeff;metalink上的文章較全的&#xff0c;中文的可參考我的博客EBS開發技術之trace http://blog.csdn.net/cai_xingyun/article/details/17250971 This document provides instructions on how to create and retrieve Forms and Database level SQL trace…

關于farpoint公司的控件:SPREAD for .NET Windows Forms Ed.的一些簡單方法.

View Code using System;using FarPoint.Win.Spread ;using System.Drawing;using System.Windows.Forms;namespace DFO010{/// <summary>/// Fpspread的相關函數.2006/4/12 制作:Chouka/// </summary> public class Classspd {public Classspd() { }/// <su…

永遠的beyond!(4 days left to get back touch)

永遠的beyond!轉載于:https://www.cnblogs.com/LaoLuo/archive/2012/03/05/2380954.html

串行總線協議筆記

I2C --INTER-IC串行總線的縮寫&#xff0c;是PHILIPS公司推出的芯片間串行傳輸總線。它以1根串行數據線&#xff08;SDA&#xff09;和1根串行時鐘線&#xff08;SCL&#xff09;實 現了雙工的同步數據傳輸。具有接口線少&#xff0c;控制方式簡化&#xff0c;器件封裝形式小&a…

ibm服務器和微軟,微軟與IBM不得不說的事情

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓在Windows 3.x 開 始 為 世 人 接 受 之 初&#xff0c; 個 人 電 腦 的 操 作 系 統 中 唯 一 可 以 與Windows 操 作 系 統 分 庭 抗 禮 的 就 是OS/2。 這 套 原 先 是 微 軟 與IBM 合 作 生 產 的 操 作 系 統&#xff0c; 由 …

[置頂] 程序員編程生產力相差10倍意味著什么?

在軟件工程研究中&#xff0c;被驗證得最多的結論就是對于同等經驗的兩個不同程序員&#xff0c;在效率和質量上可能會有10倍的差距。研究人員還發現&#xff0c;這種差距也適用于團隊級別上&#xff0c;也就是說在同一行業內的不同的團隊也是如此。 軟件開發中的個人效率的變化…