日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

ORACLE---Unit04: SQL(高级查询)

發布時間:2023/12/20 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ORACLE---Unit04: SQL(高级查询) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

---(重點復習:子查詢、分頁查詢、decode)
--- SQL(高級查詢)

--- 子查詢
--- 子查詢是嵌套在其它SQL語句當中的,目的是為嵌套的SQL提供數據,以便其執行。

---查看誰的工資高于CLARK?
---1.先查CLARK的工資
SELECT sal FROM emp_RR WHERE ename='CLARK';
--->2450
---2.工資高于CLARK的員工信息
SELECT ename,sal FROM emp_RR WHERE sal>2450;
--->5條

SELECT ename,sal FROM emp_RR WHERE sal>
(SELECT sal FROM emp_RR WHERE ename='CLARK');
---子查詢加括號,放在括號里面。為了外層數據,而提供數據的。

---查詢誰跟FORD一個部門的
SELECT ename,deptno FROM emp_RR WHERE deptno=
(SELECT deptno FROM emp_RR dept_RR WHERE ename='FORD'); ---查看20號部門的員工
--->4條記錄
SELECT * FROM dept_RR;

---查看工資高于公司平均工資的員工?
SELECT ename,sal FROM emp_RR WHERE sal>
(SELECT AVG(sal) FROM emp_RR );

---查看公司最高工資是誰?
SELECT ename,sal FROM emp_RR WHERE sal=
(SELECT MAX(sal) FROM emp_RR); ---最高工資5000

---查看部門的平均工資,前提是該部門的平均工資要高于30號部門的平均工資?
SELECT AVG(sal) FROM emp_RR WHERE deptno=30;
--->1566.666666666666666666666666666666666667

SELECT AVG(sal),deptno FROM emp_RR
GROUP BY deptno HAVING AVG(sal)>
(SELECT AVG(sal) FROM emp_RR WHERE deptno=30);

---在DDL與DML中也可以使用子查詢
---1:在DDL中使用子查詢,可以將一個子查詢的結果集當做表快速創建。

---創建一張表,含有empno,ename,sal,job,deptno,dname,loc.
---并且數據就是現有表emp,dept中的數據?

CREATE TABLE emp_RRYY AS
SELECT e.empno,e.ename,e.sal,e.job,d.deptno,d.dname,d.loc FROM emp_RR e,dept_RR d
WHERE e.deptno=d.deptno(+);
--->少了scott
--->table EMP_RRYY 已創建。
DESC emp_RRYY
SELECT * FROM emp_RRYY;
DROP TABLE emp_RRYY;
--->table EMP_RRYY已刪除。

CREATE TABLE emp_RRYY AS
SELECT e.empno id,e.ename name ,e.sal,e.job,d.deptno,d.dname,d.loc FROM emp_RR e,dept_RR d
WHERE e.deptno=d.deptno(+);
---在子查詢中,如果字段取了別名,新創建的表對應的字段就是用的別名。沒有別名,就是用字段名。

---DML中使用子查詢
---將SIMTH所在部門所有員工工資上浮10%
SELECT deptno FROM emp_RR WHERE ename='SMITH'; ---SMITH部門號是20

UPDATE emp_RR SET sal=sal*1.1 WHERE deptno=
(SELECT deptno FROM emp_RR WHERE ename='SMITH');
--->4 行已更新。
ROLLBACK;
--->回退完成。
SELECT * FROM emp_RR;

---將SIMITH所在部門的員工都刪了
DELETE FROM emp_RR WHERE deptno=
(SELECT deptno FROM emp_RR WHERE ename='SMITH');
--->4 行已刪除。(只有10條記錄了)
ROLLBACK;
--->回退完成。


--- 一、子查詢 (像Java中的內部類,嵌套在其它SQL語句當中的)
--- 1.子查詢在WHERE子句中
--- 1.1)在SELECT查詢中,在WHERE查詢條件中的限制條件不是一個確定的值,而是來自于另外一個查詢的結果
--- 1.2)為了給查詢提供數據而首先執行的查詢語句叫做子查詢
--- 1.3)子查詢是嵌入在其它SQL語句中的SELECT語句,大部分時候出現在WHERE子句中
--- 1.4)子查詢嵌入的語句稱作主查詢或父查詢
--- 1.5)主查詢可以是SELECT語句,也可以是其它類型的語句比如DML或DDL語句


--- 1.6)根據飯后結果的不同,子查詢可分為單行子查詢、多行子查詢及多列子查詢
--- 1)單行單列子查詢:一行一列就是一個值。
--- 單列大多數當做過濾條件,放在where、having里去使用。
--- 2)多行單列子查詢:多行一列就是好幾個值。
--- 3)多行多列子查詢:多行多列就是兩個維度。
--- 多列大多數當做一張表使用,表進行查詢工作。
--- 1.7)
---查找和SCOTT同職位的員工:
SELECT e.ename,e.job FROM emp_RR e
WHERE e.job=
(SELECT job FROM emp_RR WHERE ename='SCOTT'); ---先執行子查詢得到結果后再進行主查詢
---查找薪水比整個機構平均薪水高的員工
SELECT deptno,ename,sal
FROM emp_RR e
WHERE sal>(SELECT AVG(sal)FROM emp_RR);

---子查詢根據查詢結果不同,分為:單行單列子查詢、多行單列子查詢和多行多列子查詢。
---其中單列子查詢常用在過濾條件中,而多列子查詢通常當做表看待。

---對于多行單列子查詢在作為過濾條件進行判斷時,要配合IN、ANY、ALL使用

---查看與SALESMAN同部門的其他職位員工?
SELECT deptno,ename FROM emp_RR WHERE job='SALESMAN';

SELECT ename,job,deptno FROM emp_RR WHERE deptno=
(SELECT deptno FROM emp_RR WHERE job='SALESMAN');
--->ORA-01427: 單行子查詢返回多個行

SELECT ename,job,deptno FROM emp_RR WHERE deptno IN
(SELECT deptno FROM emp_RR WHERE job='SALESMAN');

SELECT ename,job,deptno FROM emp_RR WHERE deptno IN
(SELECT deptno FROM emp_RR WHERE job='SALESMAN')
AND job<>'SALESMAN';

---查看比職位是SALESMAN和CLERK工資都高的員工?
SELECT ename,sal FROM emp_RR
WHERE sal>ALL(SELECT sal FROM emp_RR WHERE job IN('SALESMAN','CLERK'));


--- 1.8)如果子查詢返回多行,主查詢中要使用多行比較操作符
--- 1.9)多行比較操作符包括IN、ALL、ANY。其中ALL和ANY不能單獨使用,
--- 需要配合單行比較操作符>、>=、<、<=一起使用
---查詢出部門中有SALESMAN但職位不是SALESMAN的員工的信息:
SELECT empno,ename,job,sal,deptno
FROM emp_RR
WHERE deptno IN
(SELECT deptno FROM emp_RR WHERE job='SALESMAN') ---子查詢的結果是多個值
AND job<>'SALESMAN';

--- 2.0)在子查詢中需要引用到主查詢的字段數據,使用EXISTS關鍵字
--- 2.1)EXISTS后邊的子查詢至少返回一行數據,則整個條件返回TRUE.
--- 2.2)列出來那些有員工的部門信息
SELECT deptno,dname FROM dept_RR d
WHERE EXISTS
(SELECT * FROM emp_RR e WHERE d.deptno=e.deptno);

---EXISTS關鍵字
---EXISTS關鍵字用在過濾條件中,其后需要跟一個子查詢,當該子查詢可以查詢出至少一條記錄時,即判斷為滿足條件。

---查看有員工的部門?
SELECT d.deptno,d.dname,d.loc FROM dept_RR d ---查出dept表中的所有信息
WHERE EXISTS
(SELECT * FROM emp_RR e WHERE e.deptno=d.deptno);
--->40號部門沒有

SELECT d.deptno,d.dname,d.loc FROM dept_RR d
WHERE NOT EXISTS
(SELECT * FROM emp_RR e WHERE e.deptno=d.deptno);
--->40 OPERATIONS BOSTON

---查看有下屬的員工?
SELECT m.empno,m.ename,m.sal FROM emp_RR m
WHERE EXISTS
(SELECT * FROM emp_RR e WHERE e.mgr=m.empno);


--- 2.子查詢在HAVING子句中
---查詢列出最低薪水高于部門30的最低薪水的部門信息
SELECT deptno,MIN(sal) min_sal FROM emp_RR
GROUP BY deptno
HAVING MIN(sal)>
(SELECT MIN(sal)FROM emp_RR WHERE deptno=30);

--- 3.子查詢在FROM部分
--- 3.1)FROM子句用來指定要查詢的表
--- 3.2)如果要在一個子查詢的結果中繼續查詢,則子查詢出現在FROM 子句中,這個子查詢也稱作行內視圖或匿名視圖
--- 3.3)把子查詢當做視圖對待,但視圖沒有名字,只能在當前的SQL語句中有效

---查詢出薪水比本部門平均薪水高的員工信息
SELECT e.deptno,e.ename,e.sal FROM emp_RR e,
(SELECT deptno,AVG(sal) avg_sal FROM emp_RR GROUP BY deptno)x
WHERE e.deptno=x.deptno and e.sal>x.avg_sal
ORDER BY e.deptno;

---FROM子句中使用子查詢
---當一個子查詢為多列子查詢時,通常是當做一張表使用出現在FROM子句中

---查看誰的工資高于自己所在部門平均工資?
---1.每個部門的平均工資是多少
SELECT AVG(sal),deptno FROM emp_RR GROUP BY deptno;
--->有4個部門的平均工資數

SELECT deptno,AVG(sal)FROM emp_RR GROUP BY deptno;

---SELECT e.ename,e.sal,e.deptno FROM emp_RR e,T t
---WHERE e.deptno=t.deptno
---AND e.sal>t.AVG(sal);

SELECT e.ename,e.sal,e.deptno FROM emp_RR e,(SELECT deptno,AVG(sal)FROM emp_RR GROUP BY deptno) t
WHERE e.deptno=t.deptno
AND e.sal>t.AVG(sal);
--->ORA-00904: "T"."AVG": 標識符無效
--->聚合函數:不能出現變量值。

SELECT e.ename,e.sal,e.deptno FROM emp_RR e,(SELECT deptno,AVG(sal) avg_sal FROM emp_RR GROUP BY deptno) t
WHERE e.deptno=t.deptno
AND e.sal>t.avg_sal;

---查看每個部門最高工資是誰?
SELECT e.ename,e.sal,e.deptno FROM emp_RR e,(SELECT deptno,MAX(sal) max_sal FROM emp_RR GROUP BY deptno) t
WHERE e.deptno=t.deptno
AND e.sal=t.max_sal;


--- 4.子查詢在SELECT部分(把查詢的結果當成字段來用)
--- 把子查詢放在SELECT 子句部分,可以認為是外連接的另一種表現形式,使用更靈活
SELECT e.ename,e.sal,
(SELECT d.deptno FROM dept_RR d WHERE d.deptno=e.deptno) deptno
FROM emp_RR e;


SELECT e.ename,e.sal,
(SELECT d.dname FROM dept_RR d WHERE d.deptno=e.deptno) dname
FROM emp_RR e;
---外連接的寫法
---把查詢的結果當成字段值來用(這種查詢將來用的少,大部分子查詢都是用在WHERE,HAVING里)


---分頁查詢
---當一個查詢語句查詢的數據量非常大時,需要分批分段將數據查詢出來,這樣做可以減少系統資源開銷,提高數據庫響應速度。
---分頁由于在標準SQL中沒有定義,所以不同的數據庫有不同的語法,即:方言。

---ROWNUM:偽列
---ORACLE提供了偽列:ROWNUM來配合完成分頁查詢。
---ROWNUM不存在與任何表中,但是所有的表都可以查詢該字段。該字段的值在結果集中就是每條記錄的行號。
---ROWNUM的值是動態生成的,是伴隨查詢的過程中生成的。即:每當可以從表中查詢出一條記錄時,
---ROWNUM會為該條記錄生成行號,從1開始逐一遞增。
SELECT ROWNUM ename,sal,job,deptno FROM emp_RR;

---查詢6到10???正常是一條記錄都沒有。
SELECT ROWNUM ename,sal,job,deptno FROM emp_RR WHERE ROWNUM BETWEEN 6 AND 10;
--->假的SQL?O(∩_∩)O哈哈~why?下午再說PM SEE YOU LA LA


---在使用ROWNUM對結果集編號的過程中不要使用ROWNUM做>1以上數字的判斷,否則查詢不出任何結果。
SELECT ROWNUM ename,sal,job,deptno FROM emp_RR WHERE ROWNUM>1;
SELECT ROWNUM ename,sal,job,deptno FROM emp_RR WHERE ROWNUM<10;

SELECT * FROM(SELECT ROWNUM,ename,sal,job,deptno FROM emp_RR)WHERE ROWNUM BETWEEN 6 AND 10;
--->然并卵!外層的rownum不是里面的字段
SELECT * FROM(SELECT ROWNUM rn,ename,sal,job,deptno FROM emp_RR)WHERE rn BETWEEN 6 AND 10;

---工資排名6到10的人。
SELECT * FROM(SELECT ROWNUM rn,ename,sal,job,deptno FROM emp_RR)WHERE rn BETWEEN 6 AND 10
ORDER BY sal DESC;
--->ORDER BY是最后干。

SELECT *
FROM(SELECT ROWNUM rn,t. *
FROM(SELECT ename,sal,job deptno FROM emp_RR ORDER BY sal DESC)t)
WHERE rn BETWEEN 6 AND 10;
---先排序,后編號,再取范圍。套兩個子查詢。雖然查出來,但是效率較低。
---排序一定要干的,編號上可以讓它效率更高一些,

SELECT *
FROM(SELECT ROWNUM rn,t. *
FROM(SELECT ename,sal,job deptno FROM emp_RR ORDER BY sal DESC)t WHERE ROWNUM <=10)
WHERE rn >=6;
---在里層編號的內容,多余的就可以省去了。提高效率。

--- 二、分頁查詢(分段查詢---淘寶、京東搜一個U盤有成千上萬個,不會在同一頁...56K貓,一撥號上網,電話就不能打了。多圖殺貓。擒拿少取)
---ORACLE的分頁和MySQL的分頁寫法不一樣
--- 1.ROWNUM
--- 1.1) 被稱作偽列,用于返回標識行數據順序的數字
SELECT ROWNUM,empno,ename,sal FROM emp_RR;
--- 1.2) 只能從1計數,不能從結果集中直接截取
SELECT ROWNUM,empno,ename,sal FROM emp_RR WHERE rownum>3; ---查詢不到結果
--- 1.3)利用ROWNUM截取結果集中的部分數據,需要用到行內視圖
SELECT * FROM
(SELECT ROWNUM rn,e.*FROM emp e) ---給ROWNUM一個別名
WHERE rn BETWEEN 8 AND 10;

--- 2.使用子查詢進行分頁
--- 2.1)分頁策略:每次只取一頁的數據。每次換頁,取下一頁的數據。
--- 2.2)在oracle中利用ROWNUM的功能可用來進行分頁
--- 2.3)假設結果集共105條,每20條分為一頁,則:
--- Page1:1至20
--- Page2:21至40
--- ...
--- PageN:(n-1)*pageSize+1至n*pageSize
--- 共6頁

--- 3.分頁與ORDER BY
--- 3.1)按薪水倒序排列,取出結果集中第8到第10條的記錄
SELECT * FROM (SELECT ROWNUM rn,t.*FROM
(SELECT empno,ename,sal FROM emp_RR ORDER BY sal DESC)t)
WHERE rn BETWEEN 8 AND 10

--- 3.2)根據要查看的頁數,計算起點值((n-1)*pageSize+1)和終點值(n*pageSize),
--- 替換掉BETWEEN和AND的參數,即得到當前頁的記錄

---在將來實際開發中,不可能讓用戶去寫這兩個數的。例如:上淘寶只需要寫上一頁、下一頁或則跳到第幾頁,最多能顯示顯示1能顯示多少條。
---從來不會讓你寫第幾條到第幾條。

---pageSize:每頁顯示的條目數
---page:頁數

---pageSize:5 page:2 --->也就是6到10條

---算法:現成的推導
---start:(page-1)*pageSize+1
---end:pageSize*page

---在Java中怎么干?將來是動態的,讓Java去執行SQL語句。動態的把SQL語句拼出來。
---偽代碼,理解就行。(下周就寫)

---******************************************************************************
package oracle;

import java.util.Scanner;

public class Test {

public static void main(String[] args) {
Scanner scanner= new Scanner(System.in);
System.out.println("請輸入每頁要顯示的條目數:");
int pageSize=Integer.parseInt(scanner.nextLine());

System.out.println("請輸入要查看的頁數");
int page=Integer.parseInt(scanner.nextLine());

int start=(page-1)*pageSize+1;
int end=pageSize * page;

String sql="SELECT *"+
"FROM(SELECT ROWNUM rn,t. *"+
" FROM(SELECT ename,sal,job deptno FROM emp_RR ORDER BY sal DESC)t WHERE ROWNUM <="+end+")"+
" WHERE rn >="+start;
System.out.println(sql);
}

}
//輸出后得到如下內容:(將來把這條語句發送到數據庫,相當于在數據庫里執行。)
//SELECT *
//FROM(SELECT ROWNUM rn,t. *
//FROM(SELECT ename,sal,job deptno FROM emp_RR ORDER BY sal DESC)t WHERE ROWNUM <=10)
//WHERE rn >=6;
---*******************************************************************************************
---到數據庫顯示:
SELECT *
FROM(SELECT ROWNUM rn,t. *
FROM(SELECT ename,sal,job deptno FROM emp_RR ORDER BY sal DESC)t WHERE ROWNUM <=10)
WHERE rn >=6;

***********************************************************************************************
---當有了框架后,就不是寫在Java只中,而是寫在配置文件中,配置文件就可以編寫SQL語句,讓Java去執行。

?


--- 三、DECODE函數
--- 1.DECODE函數基本語法
--- 1.1)DECODE(expr,search1,result1[,serch2,result2...][,default]) ---至少傳3個以上參數

--- 1.2)DECODE用于比較參數expr的值,如果匹配到哪一個search條件,就返回對應的result結果
--- 1.3)可以有多組search和result的對應關系,如果任何一個search條件都沒有匹配到,則返回最后default的值
--- 1.4)default參數是可選的,如果所有提供default參數值,當沒有匹配到時,將返回NULL.

---查詢職員表,根據職員的職位計算獎勵金額,當職位分別是'MANAGER'、'ANALYST'、'SALESMAN'時,
---獎勵金額分別是薪水的1.2倍、1.1倍、1.05倍,如果不是這三個職位,則獎勵金額取薪水值
SELECT ename,job,sal,
DECODE(job,'MANAGER',sal*1.2,'ANALYST',sal*1.1,'SALESMAN',sal*1.05,sal)bonus FROM emp_RR;

SELECT ename,job,sal,
DECODE(job,
'MANAGER',sal*1.2,
'ANALYST',sal*1.1,
'SALESMAN',sal*1.05)bonus
FROM emp_RR;
--->不返回正常工資,而返回空值null。


---和DECODE 函數功能相似的有CASE語句,實現類似于if-else的操作。(更像Java中的switch...case...)
SELECT ename,job,sal,
CASE job WHEN 'MANAGER' THEN sal*1.2
WHEN 'ANALYST' THEN sal*1.1
WHEN 'SALESMAN' THEN sal*1.05
ELSE sal END
bonus FROM emp_RR;

--- 2.DECODE函數中分組查詢中的應用
--- 2.1按字段內容分組
--- 場景:計算職位的人數,analyst/manager屬于vip,其余是普通員工operation,無法用GROUP BY簡單實現
SELECT DECODE(job,'ANALYST','VIP','MANAGER','VIP','OPERATION')job,
COUNT(1)job_cnt FROM emp_RR
GROUP BY DECODE(job,'ANALYST','VIP','MANAGER','VIP','OPERATION');

--- 2.2按字段內容排序
--- 場景:Dept表中按"OPERATIONS"、"ACCOUNTING"、"SALES"排序,無法按照字面數據排序
SELECT deptno,dname,loc FROM dept_RR
ORDER BY
DECODE(dname,'OPERATIONS',1,'ACCOUNTING',2,'SALES',3);
---自由定義排序規則.數據量少的話,可以排。
---DECODE函數不需要所有的參數,都是同一類型的,比較的是相同類型的,返回的也是相同類型的,即可。

---在分組中使用DECODE 函數可以將字段值不同的記錄劃分為一組(將來也實用)
---將MANAGER和ANALYST看作一組,其他職位看作另一組,分別統計各組人數

SELECT ename,job FROM emp_RR ORDER BY job;
SELECT COUNT(1),job FROM emp_RR GROUP BY job;
---統計人數的時候,count什么都行。出來的是有幾組職位,每個職位出來的計數。

SELECT ename,job,
DECODE(job,
'MANAGER','VIP',
'ANALYST','VIP',
'OTHER')
FROM emp_RR;


SELECT COUNT(1),
DECODE(job,
'MANAGER','VIP',
'ANALYST','VIP',
'OTHER') count_name
FROM emp_RR
GROUP BY DECODE(job,
'MANAGER','VIP',
'ANALYST','VIP',
'OTHER');

?

--- 四、排序函數(沒那么常用)
--- ROW_NUMBER、RANK、DENSE_RANK
---1.ROW_NUMBER
--- 1.1)ROW_NUMBER()OVER(PARTITION BY col1 ORDER BY col2)
--- 1.2)表示根據col1分組,在分組內部根據col2排序
--- 1.3)此函數計算的值就表示每組內部排序后的順序編號,組內連續其唯一
--- 1.4)Rownum是偽列,ROW_NUMBER功能更強,可以直接從結果集中取出子集

--- 場景:按照部門編碼分組顯示,每組內按職員編碼排序,并賦予組內編碼
SELECT deptno,ename,empno,
ROW_NUMBER()OVER(PARTITION BY deptno ORDER BY empno)AS emp_id FROM emp_RR;


---排序函數:將來在開發中解決特殊問題,它能幫你把整個的結果集按照指定的字段分組,然后在組內幫你排序。然后生成一個組內行號(編號)。
---rownum是對整個結果集123456的排序,而它不是。它是每組123456,再一組123456.

---排序函數
---排序函數可以對結果集按照指定的字段分組,然后在組內按照指定的字段排序,然后生成組內的行號。
---ROW_NUMBER:生成組內連續且唯一的數字
---查看每個部門的工資排名:
SELECT ename,sal,deptno,
ROW_NUMBER()OVER(PARTITION BY deptno ORDER BY sal DESC) rank
FROM emp_RR;
--->就像Justin biber的歌 背唄背唄... ...
---有兩人不爽:
---WARD 1250 30 4
---MARTIN 1250 30 5


---RANK:生成組內不連續也不唯一的數字
SELECT ename,sal,deptno,
RANK()OVER(PARTITION BY deptno ORDER BY sal DESC) rank
FROM emp_RR;
---WARD 1250 30 4
---MARTIN 1250 30 4
---JAMES 950 30 6--->變5

---DENSE_RANK:生成組內連續但不唯一的數字
SELECT ename,sal,deptno,
DENSE_RANK()OVER(PARTITION BY deptno ORDER BY sal DESC) rank
FROM emp_RR;
---WARD 1250 30 4
---MARTIN 1250 30 4
---JAMES 950 30 5

?

---2.RANK
--- 2.1)PANK()OVER(PARTITION BY col1 ORDER BY col2)
--- 2.2)表示根據col1分組,在分組內部根據col2給予等級標識
--- 2.3)等級標識即排名,相同的數據返回相同排名
--- 2.4)跳躍排序,如果有相同數據,則排名相同,比如并列第二,則兩行數據都標記為2,但下一位將是第四名
--- 2.5)和ROW_NUMBER的區別是有重復值,而ROW_NUMBER沒有

--- 場景:按照部門編碼分組,同組內按薪水倒序排序,相同薪水則按獎金數正序排序,并給予組內等級,用Rank_ID表示
SELECT deptno,ename,sal,comm,
RANK()OVER(PARTITION BY deptno ORDER BY sal DESC,comm) "Rank_ID" FROM emp_RR;

---3.DENSE_RANK
--- 3.1)DENSE_RANK()OVER(PARTITION BY col1 ORDER BY col2)
--- 3.2)表示根據col1分組,在分組內部根據col2給予等級標識
--- 3.3)即排名,相同的數據返回相同排名
--- 3.4)連續排序,如果有并列第二,下一個排序將是三,這一點是和RANK的不同,RANK是跳躍排序

---場景:關聯emp和dept表,按照部門編碼分組,每組內按照員工薪水排序,列出員工的部門名字、姓名和薪水
SELECT d.dname,e.ename,e.sal,
DENSE_RANK()OVER(PARTITION BY e.deptno ORDER BY e.sal)
AS drank
FROM emp_RR e join dept_RR d
on e.deptno=d.deptno;


----隨機插入一千條數據在里面:(隨機數,隨機生成。)
---ROLLUP(續3)
CREATE TABLE sales_tab_RR(
year_id NUMBER NOT NULL,
month_id NUMBER NOT NULL,
day_id NUMBER NOT NULL,
sales_value NUMBER(10,2)NOT NULL
);
INSERT INTO sales_tab_RR
SELECT TRUNC(DBMS_RANDOM.value(2010,2012))AS year_id,
TRUNC(DBMS_RANDOM.value(1,13))AS month_id,
TRUNC(DBMS_RANDOM.value(1,32))AS day_id,
ROUND(DBMS_RANDOM.value(1,100),2) AS sales_value
FROM dual
CONNECT BY level<=1000;
--->table SALES_TAB_RR 已創建。
--->1,000 行已插入。

?

?

?

--- 五、集合操作(并、交、差)
--- 1.UNION、UNION ALL
--- 1.1)為了合并多個SELECT語句的結果,可以使用集合操作符,實現集合的并、交、差
--- 1.2)集合操作符包括UNION、UNION ALL、INTERSECT和MINUS
--- 1.3)多條作集合操作的SELECT語句的列的個數和數據類型必須匹配
--- 1.4)ORDER BY子句只能放在最后的一個查詢語句中
--- 1.5)集合操作的語法如下:
---SELECT statement1
---[UNION|UNION ALL|INTERSECT|MINUS]
---SELECT statement2;

--- 1.6)用來獲取兩個或兩個以上結果集的并集
--- 1.7)UNION操作符會自動去掉合并后的重復記錄
--- 1.8)UNION ALL返回兩個結果集中的所有行,包括重復的行。
--- 1.9)UNION操作符對查詢結果排序,UNION ALL不排序

--- 2.0)合并職位是'MANAGER'的員工和薪水大于2500的員工集合,查看兩種方式的結果差別
SELECT ename,job,sal FROM emp_RR
WHERE job='MANAGER'
UNION
SELECT ename,job,sal FROM emp_RR
WHERE sal>2500;
--->6條記錄

SELECT ename,job,sal FROM emp_RR
WHERE job='MANAGER'
UNION ALL
SELECT ename,job,sal FROM emp_RR
WHERE sal>2500;
--->8條記錄

--- 2.INTERSECT
--- 2.1)獲得兩個結果集的交集,只有同時存在于兩個結果集中的數據,才被顯示輸出
--- 2.2)使用INTERSECT操作符后的結果集會以第一列的數據作升序排列
--- 2.3)顯示職位是'MANAGER'的員工薪水大于2500的員工的交集
SELECT ename,job,sal FROM emp_RR
WHERE job='MANAGER'
INTERSECT
SELECT ename,job, sal FROM emp_RR
WHERE sal>2500;

--- 3.MINUS
--- 3.1)獲取兩個結果集的差集
--- 3.2)只有在第一個結果集中存在,在第二個結果集中不存在的數據,才能夠被顯示出來。也就是結果集一減去結果集的結果
--- 3.3)列出職位是MANAGER但薪水低于2500的員工記錄
SELECT ename,job,sal FROM emp_RR
WHERE job='MANAGER'
MINUS
SELECT ename,job,sal FROM emp_RR
WHERE sal>=2500;

SELECT * FROM emp_RR;

SELECT * FROM dept_RR;

?

--- 六、高級分組函數
--- ROLLUP、CUBE、GROUPING SETS
--- 1.ROLLUP
--- 1.1)ROULLUP、CUBE和GROUPING SETS運算符是GROUP BY子句的擴展,可以生成與使用UNION ALL來組合單個分組查詢時
--- 相同的結果集,用來簡化和高效的實現統計查詢
--- GROUP BY ROLLUP(a,b,c)
--- GROUP BY CUBE(a,b,c)
--- GROUP BY GROUPING SETS((a),(b))

--- 1.2)假設有表test,有a、b、c、d四個列。
---SELECT a,b,c,SUM(d)FROM test
---GROUP BY ROLLUP(a,b,c);
---等價于:
---SELECT a,b,c,SUM(d)FROM test GROUP BY a,b,c
--- UNION ALL
---SELECT a,b,null,SUM(d)FROM test GROUP BY a,b
--- UNION ALL
---SELECT a,null,null,SUM(d)FROM test GROUP BY a
--- UNION ALL
---SELECT null,null,null,SUM(d)FROM test
--- 1.3)對ROLLUP的列從右到左以一次少一列的方式進行分組直到所有列都去掉后的分組(也就是全表分組)
--- 1.4)對于n個參數的ROLLUP,有n+1次分組
--- 1.5)準備數據:2010-2011年每月每天的銷售額

?

?


----隨機插入一千條數據在里面:(隨機數,隨機生成。)
---ROLLUP(續3)
CREATE TABLE sales_tab_RR(
year_id NUMBER NOT NULL,
month_id NUMBER NOT NULL,
day_id NUMBER NOT NULL,
sales_value NUMBER(10,2)NOT NULL
);
INSERT INTO sales_tab_RR
SELECT TRUNC(DBMS_RANDOM.value(2010,2012))AS year_id,
TRUNC(DBMS_RANDOM.value(1,13))AS month_id,
TRUNC(DBMS_RANDOM.value(1,32))AS day_id,
ROUND(DBMS_RANDOM.value(1,100),2) AS sales_value
FROM dual
CONNECT BY level<=1000;
--->table SALES_TAB_RR 已創建。
--->1,000 行已插入。


SELECT year_id,month_id,day_id,sales_value
FROM sales_tab_RR;
---一個店鋪、商店每天營業的流水情況。
SELECT year_id,month_id,day_id,sales_value
FROM sales_tab_RR
ORDER BY year_id,month_id,day_id;
---給它排序。

---查看每天營業額?
SELECT year_id,month_id,day_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY year_id,month_id,day_id
ORDER BY year_id,month_id,day_id;

---查看每月營業額?(把天去了,就是年、月相同的記錄看成一組,對其求和)
SELECT year_id,month_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY year_id,month_id
ORDER BY year_id,month_id;

---查看每年營業額?
SELECT year_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY year_id;

---總共的營業額?
SELECT SUM(sales_value)
FROM sales_tab_RR;

--- 在一個結果集里這幾種情況都出現:(每、年、月、日、總共都看)
SELECT year_id,month_id,day_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY year_id,month_id,day_id
UNION ALL
SELECT year_id,month_id,null,SUM(sales_value)
FROM sales_tab_RR
GROUP BY year_id,month_id
UNION ALL
SELECT year_id,null,null, SUM(sales_value)
FROM sales_tab_RR
GROUP BY year_id
UNION ALL
SELECT null,null,null,SUM(sales_value)
FROM sales_tab_RR;
--->太長了,惡心!

---ROLLUP()函數
---GROUP BY ROLLUP(a,b,c)
---等同于
---GROUP BY a,b,c
---UNION ALL
---GROUP BY a,b
---UNION ALL
---GROUP BY a
---UNION ALL
---全表

SELECT year_id,month_id,day_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY ROLLUP(year_id,month_id,day_id)
ORDER BY year_id,month_id,day_id;

SELECT year_id,month_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY ROLLUP(year_id,month_id)
ORDER BY year_id,month_id;
--->參數每次都是逐一遞減,先按月,再按年,最后年月。


---CUBE()函數
---CUBE()函數會將所有參數的每種組合多作為一次分組方式進行統計然后將結果并在一起,
---所以分組次數為2的參數個數次方。

---CUBE立方體,所有維度都來一遍,所有組合都做一遍。
---GROUP BY CUBE(a,b,c)
---abc
---ab
---ac
---bc
---a
---b
---c
---全表
---加起來總共8種。

---四的立方就是16種。
SELECT year_id,month_id,day_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY CUBE(year_id,month_id,day_id)
ORDER BY year_id,month_id,day_id;

SELECT year_id,month_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY CUBE(year_id,month_id)
ORDER BY year_id,month_id;

---rowup還是cube都內定了分組的方式了。
---rowup字段逐一遞減,cube所有組合都來一遍。
---rowup片面格式固定,cube太全面了。
---現在有一需求,想看每天和每月的,沒意義的組合不想看。在一個結果集里。

---GROUPING SETS(比前兩個要頻繁,但這三個都不太用)
---允許自己去指定分組方式,然后幫你統計分組,再并到一個結果集里。

---GROUPING SETS()
---每一個參數是一種分組方式,然后將這些分組統計的結果并在一個結果集中顯示。
---查看每天與每月營業額?
---SELECT year_id,month_id,day_id, SUM(sales_value)
---FROM sales_tab_RR
---GROUP BY GROUPING SETS(year_id,month_id,day_id)
---ORDER BY year_id,month_id,day_id;


---GROUPING SETS(year_id,month_id,day_id)
---等同于
---GROUP BY year_id
---UNION ALL
---GROUP BY month_id

SELECT year_id,month_id,day_id, SUM(sales_value)
FROM sales_tab_RR
GROUP BY GROUPING SETS((year_id,month_id,day_id),(year_id,month_id))
ORDER BY year_id,month_id,day_id;
--->放在一個括號里,表一個參數。

轉載于:https://www.cnblogs.com/sneg/p/7813308.html

總結

以上是生活随笔為你收集整理的ORACLE---Unit04: SQL(高级查询)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。