資料庫開發(五)組函式,子查詢
阿新 • • 發佈:2018-12-01
組函式:
- 單行函式:每一行會得到一個結果
- 組函式(多行函式):一組得到一個結果,預設情況下所有的資料是一組
常用組函式(統計):
- SUM():求和
- AVG():求平均
- MAX():求最大
- MIN():求最小
- COUNT():統計個數
eg1:求所有人的工資總和
SELECT SUM(salary)
FROM s_emp;
eg2:求41號部門員工的薪資總和,平均薪資,最高薪資,最低薪資,人數
SELECT SUM(salary),AVG(salary),MAX(salary),MIN(salary),COUNT(id) SELECT SUM(salary) FROM s_emp WHERE dept_id=41;
注:
- 組函式統計不包含空值
- SUM(),AVG()僅針對於數值型統計
- MAX(),MIN(),COUNT()任何型別都可以
- COUNT(),統計個數,可以利用他統計行數,要注意,不要針對可能是空的做統計
- COUNT():主鍵列,或者*(所有列聯合不為空就可以)
- 組函式不能直接出現在WHERE條件中(WHERE篩選出結果後才能進行統計)
- SELECT中如果出現組函式,不能再出現普通的列(Oracle中有)
--不能像下面這樣 SELECT dept_id,SUM(salary) FROM s_emp;
GROUP BY子句:分組
- 語法:
SELECT FROM WHERE GROUP BY 列1,列2 ORDER BY;
- 注:
- 執行流程
- FROM->WHERE,行的篩選->GROUP BY,把行分組->SELECT,針對組的統計->ORDER BY,排序
- WHERE:分組前的篩選,GROUP BY在WHERE之後
- 組函式:一個組可以得到一個結果
- 查詢時,SELECT子句出現組函式或者有GROUP BY子句【“”組“”關係】,查詢中不能出現普通的列,但可以出現分組的列
- 可以按照多列分組,多個列值都相等的在一組
- 執行流程
eg1:列出每個部門員工的數量,最低薪水,平均薪水,最高薪水
--dept_id時分組的列,可以列出
SELECT dept_id,COUNT(id),MIN(salary),AVG(salary),MAX(salary)
FROM s_emp
GROUP BY dept_id;
訂單表和訂單明細表
- 訂單表:訂單編號,總額,使用者資訊等
- 訂單明細表:訂單明細編號,訂單編號,商品編號,數量,價格等
eg2:查詢每個訂單對應的訂單明細數量
SELECT ord_id,COUNT(item_id)
FROM s_item
GROUP BY ord_id;
eg3:查詢每個銷售對應的客戶數量,銷售編號
SELECT sales_rep_id, COUNT(id)
FROM s_customer
GROUP BY sales_rep_id;
eg4:查詢每個銷售對應的客戶數量,銷售編號,銷售名字
SELECT c.sales_rep_id, COUNT(c.id),e.first_name
FROM s_customer c, s_emp e
WHERE c.sales_rep_id=e.id
GROUP BY c.sales_rep_id,e.first_name;
--加與不加e.first_name分組結果一樣,只是為了顯示名字
eg5:查詢部門編號大於40的每個部門id,部門人數,部門名
SELECT d.id,d.name,COUNT(e.id)
FROM s_emp e,s_dept d
WHERE e.dept_id=d.id
AND d.id>40
GROUP BY d.id,d.name;
HAVING子句:
- WHERE子句:行的篩選
- HAVING:組的篩選,一定出現在分組後
- 語法:
SELECT FROM WHERE 條件,針對行 GROUP BY HAVING 條件,針對組 ORDER BY;
- 注:
- 執行流程:FROM->WHERE,行的篩選->GROUP BY,分組->HAVING,組的篩選->SELECT->ORDER BY
- 有GROUP BY,才能有HAVING
- HAVING中只能使用組函式或者分組的列
eg1:查詢部門人數高於2人的部門編號,部門人數
SELECT dept_id, COUNT(id)
FROM s_emp
GROUP BY dept_id
HAVING COUNT(id)>2;
eg2:查詢平均工資高於1100的部門編號,部門平均薪資
SELECT dept_id, AVG(salary)
FROM s_emp
GROUP BY dept_id
HAVING AVG(salary)>1100;
eg3:查詢部門所有人薪資都高於1000的部門編號
SELECT dept_id
FROM s_emp
GROUP BY dept_id
HAVING MIN(salary)>1000;
eg4:查詢職位包含sal(不區分大小寫),並且對應職位人數高於2人的職位名,人數
SELECT title,COUNT(id)
FROM s_emp
WHERE LOWER(title) LIKE '%sal%'
GROUP BY title
HAVING COUNT(id)>2;
相較於下面這種寫法,上面這種寫法效率更高
SELECT title,COUNT(id)
FROM s_emp
GROUP BY title
HAVING LOWER(title) LIKE '%sal%' AND COUNT(id)>2;
巢狀查詢:
- 查詢裡面的查詢,叫子查詢
SELECT
FROM
WHERE (
SELECT
FROM
WHERE
);
注:
- 查詢裡面巢狀的查詢需要用()括起來
- 子查詢可能出現的位置:WHERE子句,HAVING子句,FROM子句
WHERE子句中:
eg1:查詢薪資高於Mark的薪資的員工id,薪資
SELECT id, salary
FROM s_emp
WHERE salary>(
SELECT salary
FROM s_emp
WHERE first_name='Mark'
);
eg2:查詢高於平均薪資的員工id,名字和薪資
SELECT id, first_name, salary
FROM s_emp
WHERE salary>(
SELECT AVG(salary)
FROM s_emp
);
eg3:查詢薪資高於3號和4號員工的員工編號,薪資
如果子查詢返回多個結果,不能直接用>,=,<比較,多行子查詢
--子查詢產生多個結果,錯誤
SELECT id, salary
FROM s_emp
WHERE salary>(
SELECT salary
FROM s_emp
WHERE id IN(9,10)
);
--正確寫法之一(多行子查詢)
SELECT id, salary
FROM s_emp
WHERE salary>(
SELECT salary
FROM s_emp
WHERE id=9
)
AND salary>(
SELECT salary
FROM s_emp
WHERE id=10
);
/*
使用ALL,表示salary大於(小於)所有的結果 類似於AND
ANY:salary大於(小於)任意一個結果 類似於OR
IN:等於集合中的某一個
等於一般不使用ALL和ANY,而使用IN
*/
SELECT id, salary
FROM s_emp
WHERE salary>ALL(
SELECT salary
FROM s_emp
WHERE id IN(9,10)
);
--先求出最大值的方法也行(MAX)
HAVING子句中
eg1:查詢部門平均薪資高於Bela薪資的所有部門編號,平均薪資
SELECT dept_id, AVG(salary)
FROM s_emp
GROUP BY dept_id
HAVING AVG(salary)>(
SELECT salary
FROM s_emp
WHERE first_name='Bela'
);
FROM子句中:
eg1:查詢使用者 表第6~10條記錄(經典例子):
--rownum是關鍵字,所以外面的rownum與內部的rownum不同,查詢結果不正確
SELECT *
FROM (
SELECT rownum, id,first_name, salary
FROM s_emp
WHERE rownum<11
)
WHERE rownum>5;
--取別名,得到正確結果
SELECT *
FROM (
SELECT rownum rn, id,first_name, salary
FROM s_emp
WHERE rownum<11
)
WHERE rn>5;
eg2:查詢薪資最高的5個員工編號,薪資(經典例子):
--錯誤寫法1,會先取前5個,在排序
SELECT id, salary
FROM s_emp
WHERE rownum<6
ORDER BY salary DESC;
--錯誤寫法2,排序之前rownum已經確定,取到的還是前5個
SELECT id, salary
FROM(
SELECT id, salary,rownum r
FROM s_emp
ORDER BY salary DESC
)
WHERE r<6;
--正確寫法
SELECT *
FROM(
SELECT id, salary
FROM s_emp
ORDER BY salary DESC
)
WHERE rownum<6;
給結果集起別名,如下,取別名為temp,如有需要可用該方式取別名
SELECT *
FROM(
SELECT id, salary
FROM s_emp
ORDER BY salary DESC
) temp
WHERE rownum<6;
eg3:查詢薪資升序排序後第6~10的員工資訊
SELECT *
FROM(
SELECT t.*, rownum rn
FROM (
SELECT id,first_name,salary,dept_id
FROM s_emp
ORDER BY salary ASC
) t
WHERE rownum<11
)
WHERE rn>5;
至此查詢完結