資料庫高階資料過濾之SQL操作符與SELECT子句
高階資料過濾
AND操作符
要通過不止一個列進行果過濾,可以使用AND操作符對WHERE子句附加條件,用在WHERE子句中的關鍵字
OR 操作符
OR操作符與AND操作符正好相反,它告訴DBMS檢索匹配任一條件的行,事實上,許多DBMS在ORWHERE 子句的第一個條件得到滿足的情況下就不再計算第二個條件了(在第一個條件滿足時,不管第二個條件是否滿足,相應的行都將被檢索出來)
IN 操作符
In操作符用來指定條件範圍,範圍中的每個條件都可以進行匹配,in取一組逗號分隔,括在圓括號中的合法值IN 操作符允許我們在 WHERE 子句中規定多個值。
SQL IN 語法
SELECT column_name(s) FROM table_nameWHERE column_nam e IN (value1,value2,...)
IN 操作符例項
SELECT prof_name ,prod_price FROM Products WHERE vend_id IN(‘DLL01’, ’BRSo1’)ORDER BY prod_name
此SELECT 語句檢索由供應商DDL01和BRS01製造的所有產品,IN操作符後跟由逗號分隔的合法值,這些值必須在圓括號中.
你會猜測IN 操作符完成了與OR相同的功能,恭喜你答對了,下面的SQL語句完成了與上面的例子相同的工作,
SELECT prod_name,prod_price FROM Products WHERE vend_id=’DDL01’ OR vend_id=’BRS01’ ORDER BY prod_name;
in 與 =的區別
select name from student where name in ('zhang','wang','li','zhao');
與
select name from student where name='zhang' or name='li' or name='wang' or name='zhao'
的結果是相同的。
為什麼使用IN操作符呢,優點如下:
1.IN操作符的語法更清楚直觀,
2.IN的最大優點是可以包含其他的SELECT語句,能夠更動態地建立WHERE子句,
NOT操作符
WHERE子句中的NOT操作符有且只有一個功能,那就是否定其後所跟的任何條件
例項:
列出除了DLL01之外的所有供應商製造的產品
SELECT prod_name FROM Products WHERE NOT vend_id=’DLL01’ ORDER BY prod_name
這裡的NOT否定跟在其後的條件,因此,DBMS不是匹配vend_id為DLL01,而是匹配非DLL01之外的所有東西上面的例子也可以使用<>操作符完成
SELECT prod_name FROM Products WHERE NOT vend_id<>’DLL01’ ORDER BY prod_name
在簡單的WHERE子句中NOT沒有什麼優勢,但是在複雜的子句中NOT是非常有用的,例如,在與IN操作符聯合使用時,NOT可以非常簡單地找出與條件列表不匹配的行
any、all、exists 的使用
1. 資料表
有如下資料表:StudentInfo 學員資訊表,表資料如圖1 所示:
ID |
NAME |
SCORE |
CLASSNAME |
1 |
張青青 |
78 |
S1101 |
2 |
李紅 |
54 |
S1101 |
3 |
顧小強 |
86 |
S1101 |
4 |
陳喬 |
34 |
S1102 |
5 |
韓偉 |
99 |
S1102 |
圖1 學員資訊表資料
其中,ID 代表學員編號,NAME 為學員姓名,SCORE 為學員考試成績,CLASSNAME 為學員所在的班級名稱。
2. any 的使用
編寫 sql 語句查詢:S1101 班哪些學生的成績高於S1102 班的最低成績
SELECT NAME FROM studentInfo WHERE classname='S1101' AND score >(SELECT MIN(score) FROM studentInfo WHERE classname='S1102');
除此之外,我們還可以使用any:
SELECT NAME FROM studentInfo WHERE classname='S1101' AND score >ANY(SELECT score FROM studentInfo WHERE classname='S1102');
3. all 的使用
編寫sql 語句查詢:S1101 班哪些學生的成績高於S1102 班的最高成績
SELECT NAME FROM studentInfo WHERE classname='S1101' AND score >(SELECT MAX(score) FROM studentInfo WHERE classname='S1102');
除此之外,我們還可以使用all:
SELECT NAME FROM studentInfo WHERE classname='S1101' AND score >ALL(SELECT score FROM studentInfo WHERE classname='S1102');
4. exists 的使用
EXISTS 的作用比較簡單,它只關注它後面的子查詢返沒返回值,而不在乎返回多少。如果返回,則整個表示式就為真,否則為假。NOT EXISTS 關鍵字則和EXISTS 作用相反。
假設要查詢有沒有成績為 100 的學生,如果有,則將所有學生的成績都輸出,如果沒有,
則什麼都不輸出,我們使用EXISTS 實現,如下:
SELECT name,score FROM studentInfo WHERE EXISTS(SELECT * FROM studentInfo WHERE score=100);
IN與EXISTS區別
in 是把外表和內表作hash 連線,而exists是對外表作loop迴圈,每次loop迴圈再對內表進行查詢。
如果查詢的兩個表大小相當,那麼用in和exists差別不大。
如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in:
例如:表A(小表),表B(大表)
1:
select * from A where cc in (select cc from B)
效率低,用到了A表上cc列的索引;
select * from A where exists(select cc from B where cc=A.cc)
效率高,用到了B表上cc列的索引。
相反的
2:
select * from B where cc in (select cc from A)
效率高,用到了B表上cc列的索引;
select * from B where exists(select cc from A where cc=B.cc)
效率低,用到了A表上cc列的索引。
not in 和not exists
如果查詢語句使用了not in 那麼內外表都進行全表掃描,沒有用到索引;
而not extsts 的子查詢依然能用到表上的索引。
所以無論那個表大,用not exists都比not in要快。
(記錄合併)union和union all 的區別
在資料庫中,union和union all關鍵字都是將兩個結果集合併為一個,但這兩者從使用和效率上來說都有所不同。
union在進行錶鏈接後會篩選掉重複的記錄,所以在錶鏈接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。
如:
select * from test_union1
union
select * from test_union2
這個SQL在執行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,如果表資料量大的話可能會導致用磁碟進行排序。
而union all只是簡單的將兩個結果合併後就返回。這樣,如果返回的兩個結果集中有重複的資料,那麼返回的結果集就會包含重複的資料了。
從效率上說,union all要比union快很多,所以,如果可以確認合併的兩個結果集中不包含重複的資料的話,那麼就使用union all,如下:
select * from test_union1
union all
select * from test_union2
使用 union/union all 組合查詢的結果集有兩個最基本的規則:
1。所有查詢中的列數和列的順序必須相同。
2。資料型別必須相容
SELECT子句
Group By子句
首先講講GROUP BY 子句語法:
sql語句Group By用法一則
如果我們的需求變成是要算出每一間店 (store_name) 的營業額 (sales),那怎麼辦呢?在這個情況下,我們要做到兩件事:
第一,我們對於 store_name 及 Sales 這兩個欄位都要選出。
第二,我們需要確認所有的 sales 都要依照各個 store_name 來分開算。這個語法為:
SELECT "欄位1", SUM("欄位2") FROM "表格名" GROUP BY "欄位1"
示範
Store_Information 表
store_name |
Sales |
Date |
Los Angeles |
$1500 |
Jan-05-1999 |
San Diego |
$250 |
Jan-07-1999 |
Los Angeles |
$300 |
Jan-08-1999 |
Boston |
$700 |
Jan-08-1999 |
我們就打入,
SELECT store_name, SUM(Sales) FROM Store_Information GROUP BY store_name
結果:
store_name |
SUM(Sales) |
Los Angeles |
$1800 |
San Diego |
$250 |
Boston |
$700 |
例子2
SELECT column1, SUM(column2) FROM "list-of-tables" GROUP BY "column-list";
例子如下:
一個銷售表sales:
workername |
salemoney |
a1 |
3000 |
a2 |
2000 |
a3 |
1000 |
a2 |
3000 |
1.sql要求,查詢每個員工的總銷售總額:
SELECT workername,SUM(salemoney) FROM sales GROUP BY workername
2.sql要求,查詢總銷售額最大的員工姓名跟銷售額:
SELECT workername,MAX(salemoney) FROM sales GROUP BY workername
3.sql要求,查詢總銷售額大於等於2000的員工姓名跟銷售額:
SELECT workername, SUM(salemoney) FROM sales GROUP BY workername HAVING SUM(salemoney)>=2000
何時使用GROUP BY(心得)
一般業務要求出現 大於,等於,小於,最大,最小等範圍詞語,具體是使用where 還是having,要看是過濾行還是分組,也可同時使用where 和having
找出具有兩個訂單以上的顧客
SELECT cust_id ,COUNT(*) AS orders FROM Orders GROUP BYcust_id HAVING COUNT(*) >=2
找出具有兩個以上產品且其價格大於等於4的供應商
SELECT vend_id ,count(*) AS num_prods FROM Products WHERE pro_price>=4 GROUP BY vend_id HAVING COUNT(*)>=2
先找出 產品價格大於等於4的產品 再以供應商分組,返回供應商產品個數資訊,一般having再以返回的資訊作為條件對分組在進行過濾
group by 有一個原則,就是 select
後面的所有列中,沒有使用聚合函式的列,必須出現在 group
by 後面,在select 列表中指定的列要麼是group by 子句中指定的列,要麼包含聚組函式
說白了就是select 所取出的欄位 在分組裡必須有,但是排除被合計的欄位,比如
select a,b,c from table group by a,b,c這裡 group by 裡 必須有a,b,c
如果改成 select a,b,sum(c) from table groupby a,b,這裡 因為c被合計了 所以按照a,b分組就可以了
同樣的合計函式還包括max count 等等!
group by 除聚合函式外,如sum,其他函式,如decode,所修飾的資料庫欄位都要在group by 後體現到
假如一個公司下面有五個工廠,以公司id和工廠id進行group by,那麼出現的結果將會以最小單位來分組,即五條公司名稱相同但是工廠名稱不同的記錄,
Having子句
在select 語句中可以使用group by 子句將查詢出的行劃分成組,然後,使用聚組函式返回每一個組的彙總資訊,另外,可以使用having子句過濾分組,規定包括哪些分組,排除哪些分組,。
當在gropu by 子句中使用having 子句時,查詢結果中只返回滿足having條件的組。在一個sql語句中可以有where子句和having子句。having 與where 子句類似,均用於設定限定條件,where過濾指定的行,having過濾指定的組,having 子句可以出現聚組函式,在where 子句中不能使用聚組函式。
SELECT deptno,SUM(sal) FROM emp
WHERE sal>1200
GROUP BY deptno
HAVING SUM(sal)>8500
ORDER BY deptno;
一般使用GROUP BY子句時,應該也給出ORDER BY
子句,這是保證資料正確排序的唯一方法
where 子句的作用是在對查詢結果進行分組前,將不符合where條件的行去掉,即在分組之前過濾資料,條件中不能包含聚組函式,使用where條件顯示特定的行。
having 子句的作用是篩選滿足條件的組,即在分組之後過濾資料,條件中經常包含聚組函式,使用having 條件顯示特定的組,也可以使用多個分組標準進行分組。
查詢每個部門的每種職位的僱員數
SELECT deptno,job,COUNT(*) FROM emp GROUP BY deptno,job
查出每個供應商的產品數
SELECT vend_id ,COUNT(*) AS num_prods FROM Products GROUP BY vend_id
結果:
vend_id |
num_prods |
BRS01 |
3 |
DLL01 |
4 |
FNG01 |
2 |
GRUOP BY 子句指示DBMS按vend_id排序並分組資料,這就會對每個vend_id而不是整個表計算num_prods一次,從輸出中可以看出,供應商BRS01有3個產品,供應商DLL01有4個產品,而供應商FNG01有2個產品