SQL學習--Oracle

>>>>>>1.SQL(Structured Query Language):結構化查詢語言<<<<<<<<<<<<<<
◆注意:在數據中,字符串的字面量使用單引號括起來,這與JAVA不同,注意區分,雖然SQL語句不區分大小寫,但是字符串內容是區分大小寫的。
1.SQL可以分爲:
1)數據定義語言(DDL): Data Definition Language
    >>>>>用於建立、修改、刪除數據庫對象
包括:
    --CREATE:創建表或者其他對象的結構
    --DROP:刪除表或其他對象的結構
    --TRUNCATE:刪除表數據,保留表結構
    --RENAME :用於修改表名
        例:RENAME old_name TO new_name
    --ALTER:修改表或其他對象的結構
    --增加的列只能排在最後
          例1:ALTER TABLE mytable ADD(增加列) 
    --刪除不要的列
          例2:ALTER TABLE mytable DROP(column列名);
    --修改列的屬性
          例3:ALTER TABLE mytable MODIFY(改變列)
    ◆注意:修改表儘量在表中沒有數據時進行
2)數據操縱語言(DML):Data Manipulation Language
    >>>>>用於改變數據表中的數據。
       和事務相關,必須通過事務控制語句提交後才真正修改數據庫
包括:
    --INSERT:將數據插入到數據表中
    --UPDATE:更新數據表中與存在的數據
    ◆注意:在修改表的數據時,通常添加where條件,否則將修改所有數據
    --DELETE:刪除數據表中的數據
    ◆注意:刪除表中數據,通常會添加where來刪除滿足條件的記錄,如不添加where表示清空表
    --TRUNCATE :刪除表數據,保留表結構,清除表的磁盤空間,不受事務限制
3)事務控制語言(TCL):Transaction Control Language
    >>>>>用來維護數據庫的一致性。
包括:
    --COMMIT:提交,確認已經進行的數據改變
    --ROLLBACK:回滾,取消已經精細的數據改變
    --SAVEPOINT:保存點,使當前的事務可以回退到指定的保存點,便於取消部分改變
4)數據查詢語言(DQL):Date Query Language
    >>>>>用來查詢所需要的數據。
包括:
    --SELECT:用於查詢數據表
5)數據控制語言(DCL):Data Control Language
    >>>>>用於執行權限的授予和回收操作
包括:
    --GRANT:授予,用於給用戶或角色授予權限
    --REVOKE:用於收回用戶或角色已有的權限
    --CREATE USER:創建用戶
>>>>>>>>>>>>>>>>>>>2.Oracle數據類型<<<<<<<<<<<<<<<<<<
1.number 數字類型
    --number(p,s)
    --p:表示數字的總位數,p取值1-38
    --s:表示小數點後面的位數
2.char 和 varchar2  字符類型
    1)char:表示固定長度的字符類型
        --char(N) N表示佔用N個固定的字節數
        --最大2000字節
    2)varchar2:變長的字符類型
        --varchar2(N) : N表示最多能佔用N個字節數
        --最大4000字節
3.clob 字符串類型
    --存儲定長或變成字符串,最多達4GB的字符串數據
4.DATE 和 timestamp  時間類型
1)Date
    --用於定義日期時間的數據
    --長度是7個字節
    --默認:DD-MON-RR 例:11-APR-71
2)timestamp
    --保存日期和時間,精確度到ns

>>>>>>>>>>>>>>>>>>>3.字符串函數<<<<<<<<<<<<<<<<<<
1)CONCAT和”||”
    --Concat(char1,char2):返回兩個字符串連接後的結果。
    --等價操作:連接操作字符“||”
2)LENGTH(char)
    --用於返回字符串的長度
3)UPPER 、LOWER、INITCAP
    --Upper(char):用於將字符串轉換爲大寫形式
    --Lower(char):用於將字符串轉換爲小寫形式
    --Initcap(char):用於將字符串中每個單詞的首字符大寫,其他字符小寫,單詞之間用空格分開
4)TRIM、LTRIM、RTRIM
    --trim(char c1 from String c2) 去除c2兩邊的重複字符
    --LTRIM(String c1,String c2)//去除c1中左邊c2重複的字符
    --RTRIM(String c1,String c2)/去除c1中右邊c2重複的字符
    --select trim('e' from 'eeeelelllashsaeeeeetee') from dual;
    --select ltrim('eeeelelllashsaeeeeetee','e') from dual;
    --select rtrim('eeeelelllashsaeeeeetee','e') from dual;
5)LPAD 、RPAD補位函數
    --select LPAD(sal,10,' ') from emp_zxc;
    --select rpad(sal, 5, '*') from emp_zxc;
6)SUBSTR截取字符串
    --substr(char,n,m) 返回char中從M位開始取m個字符,m大於長度即取到末尾.
        n爲負數,則從尾部開始
    --select substr('abcdefg',-5,4) from dual;
7)instr查看字符串的位置
    --select instrb('thinking in java','in',4,2) from dual;

>>>>>>>>>>>>>>>>>>>4.oracle數值操作<<<<<<<<<<<<<<<<<<
1.round(n[,m]) 用於四捨五入
--n: 被處理的數字
--m: 正數取到小數點後第m位,負數取到小數點前m位,缺省默認值爲0
2.trunc(n[,m]) 用於截取
    --用法與round相似
3.mod(m,n) 
    --mod(m,n) :返回m除以n後的餘數
    --n 爲 0 ,直接返回m
4.ceil(n)和floor(n)
    --ceil(n): 取大於等於n的最小整數
    --floor(n):取小於等於n的最大整數

>>>>>>>>>>>>>>>>>>>5.oracle日期操作<<<<<<<<<<<<<<<<<<
--DATE 存儲固定爲7個字節,格式爲:
    第1字節:世紀+100
    第2字節:年
    第3字節:月
    第4字節:天
    第5字節:小時+1
    第6字節:分+1
    第7字節:秒+1
--TIMESTAMP 與Date 的區別爲還能保存小數秒,最高精度到ns
    第8-11字節;納秒
--查詢 SELECT SYSDATE/SYSTIMESTAMP FROM DUAL;

--日期轉換函數
    1)TO_DATE(char[,fmt[,nlsparams]])
        --將字符串按照定製的格式轉換爲日期類型
        char:要轉換的字符串
        fmt:格式
        nlsparams:指定日期語言
        ---例:TO_DATE('2002-01-01','YYYY-MM-DD')
    2)TO_CHAR(date,[fmt[,nlsparams]])
        --將其他類型的數據轉換爲字符類型
        ---例:TO_CHAR(date,'YYYY"年"MM"月"DD"日"')
--日期常用函數
    1)LAST_DAY(date):返回日期date所在月的最後一天
    2)ADD_MONTHS(date,i):返回日期date加上i個月後的日期值
        --如果i是小數,會被截取整數後再運算
        --如果i是負數,則獲得減去i個月後的日期值
        ---例:ADD_MONTHS(date,20*12)  //12年後
    3)months_between(date1,date2) 計算兩個日期間隔多少個月
        --返回結果是帶小數位的(間隔整月除外)
        ---例:2009-9-1到2009-10-10 返回1.29個月
    4)next_day(date,char) 返回date日期數據的下一週幾
        --數字1-7 表示週日-週六
        ---例:next_day(sysdate,4) 查詢下一個週三是幾號
    5)least(expr1[,expr2[,expr3]]...) 返回最小值
       greatest(expr1[,expr2[,expr3]]...) 返回最大值
           ---例:least(sysdate,'10-10月 -08')
    6)extract(date from datetime)
        --從參數datetime中提取參數date指定的數據,如年,月,日,小時等
        ---例:extract(year from sysdate) 

>>>>>>>>>>>>>>>>>>>6.oracle NULL操作<<<<<<<<<<<<<<<<<<
--隱式插入和顯示插入
--空值函數
    1)NVL(expr1,expr2):將NULL轉變爲非NULL值
        --如果expr1爲null,則取值expr2,expr2爲實際值
        --expr1和expr2可以是任何類型,當兩者數據類型必須一致
        ---例:nvl(comm,0) //如果comm爲null,返回0
    2)NVL2(expr1,expr2,expr3):將NULL轉變爲非NULL值
        --判斷expr1是否爲null,不是,返回expr2;是,返回expr3
        ---例:NVL2(comm,sal+comm,sal)

>>>>>>>>>>>>>>>>>>>7.oracle SQL基礎查詢<<<<<<<<<<<<<<<<<<
1.使用別名
    --語法:列的別名跟在列名後,中間可以加或不加一個“AS”關鍵字
2.查詢條件:
    1)>, <, >=, <=, !=(不等於), <>(不等於), =
        --例: SELECT * FROM emp WHERE deptno <> 10;
    2)AND,OR關鍵字
        --如果希望返回的結果必須滿足多個條件,
            應該使用AND邏輯操作符連接這些條件,
        --如果希望返回的結果滿足多個條件之一即可,
            應該使用OR邏輯操作符連接這些條件
    3)LIKE(模糊查詢)
        -- %:表示0到多個字符
        -- _:標識單個字符
        ---例:查詢職員姓名中第二個字符是‘A’的員工信息
            SELECT * FROM emp WHERE ename LIKE '_A%';
    4)IN和NOT IN (後接list)
        --IN(list)取出符合列表範圍中的數據,
        --NOT IN(list) 取出不符合此列表中的數據記錄
        ---例:SELECT * FROM emp WHERE job IN ('MANAGER','CLERK');
    5)BETWEEN…AND…
        --BETWEEN…AND…操作符用來查詢符合某個值域範圍條件的數據,
        --最常使用在數字類型的數據上,但對字符類型和日期類型數據也適用

    6)IS NULL和IS NOT NULL
        --空值是一個特殊的值,比較時不能使用”=”號,
            必須使用IS NULL,否則不能得到正確的結果
    7)ALL和ANY :表示“全部”和“任一”
        > ANY:大於最小
        < ANY:小於最大
        > ALL:大於最大
        < ALL:小於最小
        ---例:查詢薪水比職位是“SALESMAN”的人高的員工信息
        SELECT empno, ename, job, sal, deptno
        FROM emp
        WHERE sal> ANY (
        SELECT sal FROM emp WHERE job = 'SALESMAN');
    8)DISTINCT :過濾重複
        ---例:SELECT DISTINCT deptno FROM emp;
3.排序
    1)ORDER BY :對查詢出的數據按一定規則進行排序操作
        ---例:SELECT ename, sal FROM emp ORDER BY sal;
    2)ASC和DESC :升序和降序,默認是升序
        ---例:SELECT ename, sal FROM emp ORDER BY sal desc;
    3)多個列排序
        --當以多列作爲排序標準時,先按照第一列進行排序,
            如果第一列數據相同,再以第二列排序,以此類推.
        ---例:先按照部門編碼正序排列,再按照薪水降序排列
            SELECT ename, deptno, sal FROM emp
                    ORDER BY deptno ASC, sal DESC;
4.聚合函數**重要**
    --查詢時需要做一些數據統計時
        比如:查詢職員表中各部門職員的平均薪水,各部門的員工人數。
    --當需要統計的數據並不能在職員表裏直觀列出,
        而是需要根據現有的數據計算得到結果,
        這種功能可以使用聚合函數來實現,
        即:將表的全部數據劃分爲幾組數據,每組數據統計出一個結果。
        因爲是多行數據參與運算返回一行結果,
        也稱作分組函數、多行函數、集合函數。
    --用到的關鍵字:
        --GOURP BY :按什麼分組
        --HAVING :進一步限制分組結果
    --聚合函數忽略NULL值

    1)MAX和MIN :用來取得列或表達式的最大、最小值
        --可以用來統計任何數據類型,包括數字、字符和日期
        ---例:獲取機構下的最高薪水和最低薪水
            SELECT MAX(sal), MIN(sal) FROM emp;
    2)AVG和SUM :用來統計列或表達式的平均值和和值,並忽略NULL值
        --這兩個函數只能操作數字類型,
        ---例:獲得機構下全部職員的平均薪水和薪水總和
            SELECT AVG(sal),SUM(sal) FROM emp;
    3)COUNT :用來計算表中的記錄條數,並忽略NULL值
        ---例:獲取職員表中一共有多少名職員記錄
             SELECT COUNT(*) FROM emp;
5.分組GROUP BY  **重要**
    --having必須跟在GROUP BY後面,不能單獨存在
    ---例如查詢每個部門的最高薪水,且最高薪水大於4000
         SELECT deptno, MAX(sal) max_sal FROM emp
            GROUP BY deptno HAVING MAX(sal) >4000;

◆查詢語句的執行順序
    1.FROM 子句:執行順序爲從後往前、從右到左。
        --數據量較少的表儘量放在後面。
    2.WHERE子句:執行順序爲自下而上、從右到左。
        --將能過濾掉最大數量記錄的條件寫在WHERE子句的最右。
    3.GROUP BY:執行順序從左往右分組,
        --最好在GROUP BY前使用WHERE將不需要的記錄在GROUP BY之前過濾掉。
    4.HAVING 子句:消耗資源。
        --應避免使用,會在檢索出所有記錄之後纔對結果集進行過濾,需要排序等操作。
    5.SELECT子句:少用*號,儘量取字段名稱。
        --數據庫查詢數據字典將*號依次轉換成所有的列名,消耗時間。
    6.ORDER BY子句:執行順序爲從左到右排序,消耗資源。

6.關聯查詢
    --查詢兩個或兩個以上數據表或視圖的查詢叫做連接查詢
    --連接查詢通常建立在存在相互關係的父子表之間
    ---語法1:
        SELECT table1.column, table2.column
        FROM table1, table2
        WHERE table1.column1 = table2.column2;
    ---語法2:
        SELECT table1.column, table2.column
        FROM table1JOIN table2
        ON(table1.column1 = table2.column2);
    1)笛卡爾積
        --兩個表關聯查詢時,不寫連接條件,得到的結果即是笛卡爾積
        --假設兩個表的記錄條數分別是X和Y,笛卡爾積將返回X*Y條記錄
    2)等值連接
        --通常在有主外鍵關聯關係的表間建立,
            並將連接條件設定爲有關係的列,使用等號”=”連接相關的表
    3) 內連接: 返回兩個關聯表中所有滿足連接條件的記錄
        ---例:SELECT e.ename, d.dname
                FROM emp e, dept d
                WHERE e.deptno = d.deptno
    4)外連接:返回那些不滿足連接條件的記錄
        --語法:
            SELECT table1.column, table2.column
            FROM table1 [LEFT | RIGHT | FULL] JOIN table2
            ON table1.column1 = table2.column2;
    5)全連接
        --全外連接是指除了返回兩個表中滿足連接條件的記錄,
            還會返回不滿足連接條件的所有其它行。
        --即是左外連接和右外連接查詢結果的總和
        ---例:
            SELECT e.ename, d.dname
                FROM emp e FULL OUTER JOIN dept d
                ON e.deptno = d.deptno;
    6)自連接
        --特殊的連接查詢,數據的來源是一個表,
        --即關聯關係來自於單表中的多個列
        ---例如查出每個職員的經理名字,以及他們的職員編碼
            SELECT *
            FROM emp worker join emp manager
            ON worker.mgr = manager.empno;

>>>>>>>>>>>>>>>>>>>8.oracle 高級查詢<<<<<<<<<<<<<<<<<<
1.子查詢
    --在SELECT查詢中,在WHERE查詢條件中的限制條件不是一個確定的值,
        而是來自於另外一個查詢的結果。
        爲了給查詢提供數據而首先執行的查詢語句叫做子查詢
    --根據返回結果的不同,子查詢可分爲單行子查詢、多行子查詢及多列子查詢。
    ---例:查找薪水比整個機構平均薪水高的員工:
        SELECT deptno, ename, sal
        FROM emp e
        WHERE sal> (SELECT AVG(sal) FROM emp);
    1)EXISTS關鍵字
    ---例:
        SELECT deptno, dname FROM dept d
        WHERE EXISTS (SELECT * FROM emp e WHERE d.deptno = e.deptno);
    2)子查詢不僅可以出現在WHERE子句中,還可以出現在HAVING部分
    ---例:查詢列出最低薪水高於部門30的最低薪水的部門信息:
        SELECT deptno, MIN(sal) min_sal
        FROM emp
        GROUP BY deptno
        HAVING MIN(sal) > (SELECT MIN(sal) FROM emp WHERE deptno = 30);
    3)子查詢在FROM部分
    --如果要在一個子查詢的結果中繼續查詢,則子查詢出現在FROM 子句中,
        這個子查詢也稱作行內視圖或者匿名視圖
    ---例:查詢出薪水比本部門平均薪水高的員工信息
        SELECT e.deptno, e.ename, e.sal
        FROM emp e,
        (SELECT deptno, AVG(sal) avg_sal FROM emp GROUP BY deptno) x
        WHERE e.deptno = x.deptno and e.sal>x.avg_sal
        ORDER BY e.deptno;
    4)子查詢在SELECT部分
        --把子查詢放在SELECT子句部分,可以認爲是外連接的另一種表現形式
        SELECT e.ename, e.sal, e.deptno,
           (SELECT d.deptno FROM dept d 
            WHERE d.deptno = e.deptno)  deptno
        FROM emp e;
2. ORACLE 分頁查詢**重要**
    1)ROWNUM :僞列,用於返回標識行數據順序的數字,只能從1計數
        --如果利用ROWNUM截取結果集中的部分數據,需要用到行內視圖
            SELECT  * FROM 
              (SELECT  ROWNUMrn , e.* FROM emp e )  
             WHERE rn BETWEEN 8 AND 10;
    2)分頁與order by 
        SELECT  * FROM 
           (SELECT  ROWNUMrn , t.* FROM 
           (SELECT empno,ename,sal FROM emp ORDER BY sal DESC) t)  
         WHERE rn BETWEEN 8 AND 10;
    3)使用子查詢進行分頁
        --PageN: (n - 1) * pageSize + 1 至 n * pageSize
3.DECODE函數
    --語法:DECODE(expr,search1,result1[,search2,result2…][,default])
    --比較參數expr的值,
        如果匹配到哪一個search條件,就返回對應的result結果,
        可以有多組search和result的對應關係,
        如果任何一個search條件都沒有匹配到,則返回最後default的值。
    --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;
        --和DECODE函數功能相似的有CASE語句,實現類似於if-else的操作。
            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;

    --DECODE函數在分組查詢中的應用
    ---例如:計算職位的人數,analyst/manager職位屬於vip,
        其餘是普通員工operation
        SELECT DECODE(job, 'ANALYST', 'VIP', 
            'MANAGER', 'VIP', 'OPERATION') job,COUNT(1) job_cnt
        FROM emp
        GROUP BY 
        DECODE(job, 'ANALYST', 'VIP', 'MANAGER', 'VIP', 'OPERATION');

4. 排序函數
    4.1. ROW_NUMBER
    --語法:
        ROW_NUMBER() OVER(PARTITION BY col1 ORDER BY col2)
    --表示根據col1分組,在分組內部根據col2排序。
        此函數計算的值就表示每組內部排序後的順序編號,組內連續且唯一。
    --ROWNUM是僞列,
         ROW_NUMBER功能更強,可以直接從結果集中取出子集。
    --場景:按照部門編碼分組顯示,每組內按職員編碼排序,並賦予組內編碼
        SELECT *,ROW_NUMBER()
           OVER (PARTITION BY deptno ORDER BY empno) AS emp_id
           FROM emp;
    4.2. RANK
    --語法如下:
        RANK() OVER(PARTITION BY col1 ORDER BY col2)
    --表示根據col1分組,在分組內部根據col2給予等級標識,即排名,
         相同的數據返回相同排名。
    --特點是跳躍排序,如果有相同數據,則排名相同,比如並列第二,
         則兩行數據都標記爲2,但下一位將是第四名。
    --和ROW_NUMBER的區別是有結果有重複值,而ROW_NUMBER沒有。
    --場景:按照部門編碼分組,同組內按薪水倒序排序,
        相同薪水則按獎金數正序排序,並給予組內等級,用Rank_ID表示
        SELECT *,RANK() 
            OVER (PARTITION BY deptno ORDER BY sal DESC,comm) "Rank_ID"
               FROM emp;
    4.3. DENSE_RANK
    --語法:
        DENSE_RANK() OVER(PARTITION BY col1 ORDER BY col2)
    --表示根據col1分組,在分組內部根據col2給予等級標識,即排名,
        相同的數據返回相同排名。
    --特點是連續排序,如果有並列第二,下一個排序將是三,
        這一點是和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 e join dept d
           one.deptno = d.deptno;

5. 高級分組函數
    5.1. ROLLUP
    --ROLLUP、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))
    --假設有表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;
    --對ROLLUP的列從右到左以一次少一列的方式進行分組直到所有列都去掉後的分組(也就是全表分組)。對於n個參數的ROLLUP,有n+1次分組。
    --表-1 數據樣例表
    --準備數據:
        SQL>DROP TABLE sales_tab;
        SQL>CREATE TABLE sales_tab (
            year_id   NUMBER NOT NULL,
            month_id   NUMBER NOT NULL,
            day_id   NUMBER NOT NULL,
            sales_value NUMBER(10,2) NOT NULL);
        SQL>INSERT INTO sales_tab
            SELECT TRUNC(DBMS_RANDOM.value(low => 2010, high => 2012)) AS year_id,
            TRUNC(DBMS_RANDOM.value(low => 1, high => 13)) AS month_id,
            TRUNC(DBMS_RANDOM.value(low => 1, high => 32)) AS day_id,
            ROUND(DBMS_RANDOM.value(low => 1, high => 100), 2) AS sales_value
            FROM   dual
            CONNECT BY level <= 1000;
        SQL>COMMIT;
        --複習組函數的用法:
        SQL>SELECT SUM(sales_value) AS sales_value FROM   sales_tab;
        SQL>SELECT year_id, COUNT(*) AS num_rows,
            SUM(sales_value) AS sales_value
            FROM   sales_tab
            GROUP BY year_id
            ORDER BY year_id;
        SQL>SELECT year_id, month_id,
            COUNT(*) AS num_rows,
            SUM(sales_value) AS sales_value
            FROM   sales_tab
            GROUP BY year_id, month_id
            ORDER BY year_id, month_id;
    --ROLLUP函數的用法:
        SELECT year_id, month_id, 
        SUM(sales_value) AS sales_value
        FROM   sales_tab
        GROUP BY 
        ROLLUP (year_id, month_id)
        ORDER BY year_id, month_id;

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

    5.2. CUBE
        --CUBE函數的語法形式:
            GROUP BY CUBE(a, b, c)
        --每個參數可以理解爲取值爲參與分組和不參與分組兩個值的一個維度,
            所有維度取值組合的集合就是分組後的集合。
            對於n個參數的cube,有2^n次分組。
        如果GROUP BY CUBE(a,b,c),
        首先對(a,b,c)進行GROUP BY,
        然後依次是(a,b),(a,c),(a),(b,c),(b),(c),
        最後對全表進行GROUP BY操作,所以一共是2^3=8次分組。
        SELECT a,b,c,SUM(d) FROM test GROUP BY CUBE(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,c,SUM(d) FROM test GROUP BY a,c
        UNION ALL
        SELECT a,NULL,NULL,SUM(d) FROM test GROUP BY a
        UNION ALL
        SELECT NULL,b,c,SUM(d) FROM test GROUP BY b,c
        UNION ALL
        SELECT NULL,b,NULL,SUM(d) FROM test GROUP BY b
        UNION ALL
        SELECT NULL,NULL,c,SUM(d) FROM test GROUP BY c
        UNION ALL
        SELECT NULL,NULL,NULL,SUM(d) FROM test ;
    --等價於只是方便理解,其內部運行機制並不相同,其效率遠高於UNION ALL。
    --在sales_value表中使用cube函數:
        SELECT year_id, month_id,
        SUM(sales_value) AS sales_value
        FROM   sales_tab
        GROUP BY CUBE (year_id, month_id)
        ORDER BY year_id, month_id;

        SELECT year_id,  month_id, day_id,
        SUM(sales_value) AS sales_value
        FROM   sales_tab
        GROUP BY CUBE (year_id, month_id, day_id)
        ORDER BY year_id, month_id, day_id;
        1.5.3. GROUPING SETS

        --GROUPING SETS運算符可以生成與使用單個GROUP BY ROLLUP或CUBE 
            運算符所生成的結果集相同的結果集,但是使用更靈活。
            如果不需要獲得由完備的ROLLUP或CUBE運算符生成的全部分組,
            則可以使用GROUPING SETS僅指定所需的分組。
        --GROUPING SETS 列表可以包含重複的分組。
            GROUPING SETS示例:
            SELECT year_id, month_id, SUM(sales_value)  
            FROM sales_tab
            GROUP BY CUBE (year_id,month_id)
            order by 1, 2; 
            SELECT year_id, month_id, SUM(sales_value)  
            FROM sales_tab
            GROUP BY GROUPING SETS (  (year_id), (month_id))
            order by 1, 2
        --其中分組方式示例如下:
            --使用GROUP BY GROUPING SETS(a,b,c),
                則對(a),(b),(c)進行GROUP BY
            --使用GROUP BY GROUPING SETS((a,b),c), 
                則對(a,b),(c)進行GROUP BY
            --GROUPING BY GROUPING SET(a,a) , 
                則對(a)進行2次GROUP BY,GROUPING SETS的參數允許重複
6. 集合操作
    6.1. UNION、UNION ALL
    --爲了合併多個SELECT語句的結果,可以使用集合操作符,
        實現集合的並、交、差。
    --集合操作符包括UNION、UNION ALL、INTERSECT和MINUS。
    --多條作集合操作的SELECT語句的列的個數和數據類型必須匹配。
    --ORDER BY子句只能放在最後的一個查詢語句中。
    --語法如下:
        SELECT statement1
        [UNION | UNION ALL | INTERSECT | MINUS]
        SELECT statement2;
    --UNION和UNION ALL用來獲取兩個或兩個以上結果集的並集:
    --UNION操作符會自動去掉合併後的重複記錄。
    --UNION ALL返回兩個結果集中的所有行,包括重複的行。
    --UNION操作符對查詢結果排序,UNION ALL不排序。
    --例:合併職位是’MANAGER’的員工和薪水大於2500的員工集合,
        查看兩種方式的結果差別:
    --Union
        SELECT ename, job, sal FROM emp
        WHERE job = 'MANAGER'
        SELECT ename, job, sal FROM emp
        WHERE sal> 2500;
    --Union all
        SELECT ename, job, sal FROM emp
        WHERE job = 'MANAGER'
        SELECT ename, job, sal FROM emp
        WHERE sal> 2500;
    6.2. INTERSECT (intersect)
    --INTERSECT函數獲得兩個結果集的交集,
        只有同時存在於兩個結果集中的數據,才被顯示輸出。
    --使用INTERSECT操作符後的結果集會以第一列的數據作升序排列。
    ---例:顯示職位是’MANAGER’的員工和薪水大於2500的員工的交集:
        SELECT ename, job, sal FROM emp
        WHERE job = 'MANAGER'
        INTERSECT
        SELECT ename, job, sal FROM emp
        WHERE sal> 2500;
    6.3. MINUS
    --MINUS函數獲取兩個結果集的差集。
    --只有在第一個結果集中存在,在第二個結果集中不存在的數據,
        才能被顯示出來。也就是結果集一減去結果集二的結果。
    ---例:列出職位是MANAGER但薪水低於2500的員工記錄:
        SELECT ename, job, sal FROM emp
        WHERE job = 'MANAGER'
        MINUS
        SELECT ename, job, sal FROM emp
        WHERE sal> 2500;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章