1. 程式人生 > 資料庫 >mySQL筆記(七):子查詢

mySQL筆記(七):子查詢

#進階7:子查詢
/*
說明:當一個查詢語句中又嵌套了另一個完整的select語句,則被巢狀的select語句稱為子查詢或內查詢
外面的select語句稱為主查詢或外查詢。

分類:
按子查詢出現的位置進行分類:
1、select後面
	要求:子查詢的結果為單行單列(標量子查詢)
2、from後面
	結果可以為多行多列
3、where或having後面
	子查詢的結果必須為單列
	單行子查詢
	多行子查詢
4、exists後面
	子查詢結果必須為單列(相關子查詢)
	
特點:
	1、子查詢放在條件中,要求必須放在條件的右側
	2、子查詢一般放在小括號中
	3、子查詢的執行優於主查詢
	4、單行子查詢對應了 單行操作符:> < >= <= = <>
	   多行子查詢對應了 多行操作符:any/some all in
	   
*/
#一、放在where或having後面
	#一)單行子查詢(標量子查詢)

#案例1:誰的工資比 Abel 高?
1、查詢Abel的工資
SELECT `salary`
FROM `employees`
WHERE `last_name` = 'Abel';
2、查詢員工的細膩,滿足工資>1中的結果
SELECT *
FROM `employees`
WHERE `salary`>(
	SELECT `salary`
	FROM `employees`
	WHERE `last_name` = 'Abel'
	);
#案例2:返回job_id與141號員工相同,salary比143號員工多的員工姓名,job_id 和工資
SELECT `job_id`
FROM `employees`
WHERE `employee_id` = 141;

SELECT `salary`
FROM `employees`
WHERE `employee_id` = 143;

SELECT `last_name`,`job_id`,`salary`
FROM `employees`
WHERE `job_id` = (
	SELECT `job_id`
	FROM `employees`
	WHERE `employee_id` = 141
) 
AND
`salary`>(
	SELECT `salary`
	FROM `employees`
	WHERE `employee_id` = 143
);
#案例3:返回公司工資最少的員工的last_name,job_id和salary
SELECT `last_name`,`salary`
FROM `employees`
WHERE `salary` = (
	SELECT MIN(`salary`)
	FROM `employees`
);
#案例4:查詢最低工資大於50號部門最低工資的部門id和其最低工資
SELECT `department_id`,MIN(`salary`)
FROM `employees`
GROUP BY `department_id`
HAVING MIN(`salary`)>(
	SELECT MIN(`salary`)
	FROM `employees`
	WHERE `department_id` = 50
);
-- ##########################練習
#1、查詢和 Zlotkey 相同部門的員工姓名和工資
SELECT `last_name`,`salary`
FROM `employees`
WHERE `department_id` = (
	SELECT `department_id`
	FROM `employees`
	WHERE `last_name` = 'Zlotkey'
	);
#2、查詢工資比公司平均工資高的員工的員工號,姓名和工資。
SELECT `employee_id`,`last_name`,`salary`
FROM `employees`
WHERE `salary`>(
	SELECT AVG(`salary`)
	FROM `employees`
);
-- ###########################
	#二)多行子查詢
/*
in:判斷某欄位是否在指定列表內  
	x in(10,30,50)
any/some:判斷某欄位的值是否滿足其中任意一個
	x>any(10,50),大於任意一個
	x>min()

	x=any(10,50)
	x in(10,50)二者等價
	
all:判斷某欄位的值是否滿足裡面所有的
	x >all(10,50),大於所有的
	x >max()
*/
#案例1:返回location_id是1400或1700的部門中的所有員工姓名
SELECT `last_name`
FROM `employees`
WHERE `department_id` IN(
	SELECT DISTINCT `department_id`
	FROM `departments`
	WHERE `location_id` IN(1400,1700)
);
#案例2:返回其它部門中比job_id為‘IT_PROG’部門任一工資低的員工的員工號、姓名、job_id 以及salary
SELECT `employee_id`,`salary`
FROM `employees`
WHERE `salary` <ANY(
	SELECT `salary`
	FROM `employees`
	WHERE `job_id` = 'IT_PROG'
);
等價於
SELECT `employee_id`,`salary`
FROM `employees`
WHERE `salary` <(
	SELECT MAX(`salary`)
	FROM `employees`
	WHERE `job_id` = 'IT_PROG'
);
#案例3:返回其它部門中比job_id為‘IT_PROG’部門所有工資都低的員工的員工號、姓名、job_id 以及salary
SELECT `employee_id`,`salary`
FROM `employees`
WHERE `salary` <ALL(
	SELECT `salary`
	FROM `employees`
	WHERE `job_id` = 'IT_PROG'
);
等價於
SELECT `employee_id`,`salary`
FROM `employees`
WHERE `salary` <(
	SELECT MIN(`salary`)
	FROM `employees`
	WHERE `job_id` = 'IT_PROG'
);

#二、放在select後面
#案例;查詢部門編號是50的員工個數
SELECT(
	SELECT COUNT(*)
	FROM `employees`
	WHERE `department_id` = 50
) 個數;

#三、放在from後面(表子查詢)
#案例:查詢每個部門的平均工資的工資級別
#1、每個部門的平均工資
SELECT `department_id`,AVG(`salary`)
FROM `employees`
GROUP BY `department_id`;
#將1和`job_grades`兩表連線
SELECT 
  `department_id`,`grade_level` 
FROM
  `job_grades` g JOIN
  (SELECT 
    AVG(`salary`) ag,`department_id`
  FROM
    `employees` 
  GROUP BY `department_id`) dep_ag 
  ON dep_ag.ag BETWEEN g.`lowest_sal` 
  AND g.`highest_sal`;


#四、放在exists後面

#案例1 :查詢有無名字叫“張三丰”的員工資訊

SELECT EXISTS(
	SELECT * 
	FROM `employees`
	WHERE `last_name` = '張三丰'
) 有無張三丰;