1. 程式人生 > >資料庫開發(五)組函式,子查詢

資料庫開發(五)組函式,子查詢

組函式:

  • 單行函式:每一行會得到一個結果
  • 組函式(多行函式):一組得到一個結果,預設情況下所有的資料是一組

常用組函式(統計):

  • 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;

至此查詢完結