1. 程式人生 > 實用技巧 >97.java基礎11mysql資料庫1

97.java基礎11mysql資料庫1

1.mysql基礎1(基礎查詢)

#進階1:基礎查詢
/*
語法:
select 查詢列表 from 表名;
類似於:System.out.println(列印東西);
特點:
1、查詢列表可以是:表中的欄位、常量值、表示式、函式
2、查詢的結果是一個虛擬的表格
*/
USE myemployees;
#1.查詢表中的單個欄位
SELECT last_name FROM employees;
#2.查詢表中的多個欄位
SELECT last_name,salary,email FROM employees;
#3.查詢表中的所有欄位
#方式一:
SELECT 
    `employee_id`,
    `first_name`,
    `last_name`,
    `phone_number`,
    `last_name`,
    `job_id`,
    `phone_number`,
    `job_id`,
    `salary`,
    `commission_pct`,
    `manager_id`,
    `department_id`,
    `hiredate` 
FROM
    employees ;
#方式二:  
 SELECT * FROM employees;
 #4.查詢常量值
 SELECT 100;
 SELECT 'john';
 #5.查詢表示式
 SELECT 100%98;
 #6.查詢函式
 SELECT VERSION();
 #7.起別名
 /*
 ①便於理解
 ②如果要查詢的欄位有重名的情況,使用別名可以區分開來
 */
 #方式一:使用as
SELECT 100%98 AS 結果;
SELECT last_name AS 姓,first_name AS 名 FROM employees;
#方式二:使用空格
SELECT last_name 姓,first_name 名 FROM employees;
#案例:查詢salary,顯示結果為 out put
SELECT salary AS "out put" FROM employees;
#8.去重
#案例:查詢員工表中涉及到的所有的部門編號
SELECT DISTINCT department_id FROM employees;
#9.+號的作用
/*
sql中的+號:
①運算子,兩個運算元都為數值型
②連線符,只要有一個運算元為字串
mysql中的+號:
僅僅只有一個功能:運算子
select 100+90; 兩個運算元都為數值型,則做加法運算
select '123'+90;只要其中一方為字元型,試圖將字元型數值轉換成數值型
			如果轉換成功,則繼續做加法運算
select 'john'+90;	如果轉換失敗,則將字元型數值轉換成0

select null+10; 只要其中一方為null,則結果肯定為null

*/
#案例:查詢員工名和姓連線成一個欄位,並顯示為 姓名
SELECT CONCAT('a','b','c') AS 結果;
SELECT 
	CONCAT(last_name,first_name) AS 姓名
FROM
	employees;

2.mysql基礎2(條件查詢)

#進階2:條件查詢
/*
語法:
	select 
		查詢列表
	from
		表名
	where
		篩選條件;
分類:
	一、按條件表示式篩選
	簡單條件運算子:> < = != <> >= <=
	二、按邏輯表示式篩選
	邏輯運算子:
	作用:用於連線條件表示式
		&& || !
		and or not
	&&和and:兩個條件都為true,結果為true,反之為false
	||或or: 只要有一個條件為true,結果為true,反之為false
	!或not: 如果連線的條件本身為false,結果為true,反之為false
	三、模糊查詢
		like
		between and
		in
		is null
*/
#一、按條件表示式篩選
#案例1:查詢工資>12000的員工資訊
SELECT 
	*
FROM
	employees
WHERE
	salary>12000;
#案例2:查詢部門編號不等於90號的員工名和部門編號
SELECT 
	last_name,
	department_id
FROM
	employees
WHERE
	department_id<>90;
#二、按邏輯表示式篩選
#案例1:查詢工資z在10000到20000之間的員工名、工資以及獎金
SELECT
	last_name,
	salary,
	commission_pct
FROM
	employees
WHERE
	salary>=10000 AND salary<=20000;
#案例2:查詢部門編號不是在90到110之間,或者工資高於15000的員工資訊
SELECT
	*
FROM
	employees
WHERE
	NOT(department_id>=90 AND  department_id<=110) OR salary>15000;
#三、模糊查詢
/*
like
between and
in
is null|is not null
*/
#1.like
/*
特點:
①一般和萬用字元搭配使用
	萬用字元:
	% 任意多個字元,包含0個字元
	_ 任意單個字元
*、
#案例1:查詢員工名中包含字元a的員工資訊
select 
	*
from
	employees
where
	last_name like '%a%';#abc
#案例2:查詢員工名中第三個字元為e,第五個字元為a的員工名和工資
select
	last_name,
	salary
FROM
	employees
WHERE
	last_name LIKE '__n_l%';
#案例3:查詢員工名中第二個字元為_的員工名
SELECT
	last_name
FROM
	employees
WHERE
	last_name LIKE '_$_%' ESCAPE '$';
#2.between and
/*
①使用between and 可以提高語句的簡潔度
②包含臨界值
③兩個臨界值不要調換順序
*/
#案例1:查詢員工編號在100到120之間的員工資訊
SELECT
	*
FROM
	employees
WHERE
	employee_id >= 120 AND employee_id<=100;
#----------------------
SELECT
	*
FROM
	employees
WHERE
	employee_id BETWEEN 120 AND 100;
#3.in
/*
含義:判斷某欄位的值是否屬於in列表中的某一項
特點:
	①使用in提高語句簡潔度
	②in列表的值型別必須一致或相容
	③in列表中不支援萬用字元
*/
#案例:查詢員工的工種編號是 IT_PROG、AD_VP、AD_PRES中的一個員工名和工種編號
SELECT
	last_name,
	job_id
FROM
	employees
WHERE
	job_id = 'IT_PROT' OR job_id = 'AD_VP' OR JOB_ID ='AD_PRES';
#------------------
SELECT
	last_name,
	job_id
FROM
	employees
WHERE
	job_id IN( 'IT_PROT' ,'AD_VP','AD_PRES');
#4、is null
/*
=或<>不能用於判斷null值
is null或is not null 可以判斷null值
*/
#案例1:查詢沒有獎金的員工名和獎金率
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE
	commission_pct IS NULL;
#案例1:查詢有獎金的員工名和獎金率
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE
	commission_pct IS NOT NULL;
#----------以下為×
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE 
	salary IS 12000;
#安全等於  <=>
#案例1:查詢沒有獎金的員工名和獎金率
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE
	commission_pct <=>NULL;
#案例2:查詢工資為12000的員工資訊
SELECT
	last_name
	salary
FROM
	employees
WHERE 
	salary <=> 12000;
#is null pk <=>
IS NULL:僅僅可以判斷NULL值,可讀性較高,建議使用
<=>    :既可以判斷NULL值,又可以判斷普通的數值,可讀性較低

3.mysql基礎3(排序查詢):

#進階3:排序查詢
/*
語法:
select 查詢列表
from 表名
【where  篩選條件】
order by 排序的欄位或表示式;
特點:
1、asc代表的是升序,可以省略
desc代表的是降序
2、order by子句可以支援 單個欄位、別名、表示式、函式、多個欄位
3、order by子句在查詢語句的最後面,除了limit子句
*/
#1、按單個欄位排序
SELECT * FROM employees ORDER BY salary DESC;
#2、新增篩選條件再排序
#案例:查詢部門編號>=90的員工資訊,並按員工編號降序
SELECT *
FROM employees
WHERE department_id>=90
ORDER BY employee_id DESC;
#3、按表示式排序
#案例:查詢員工資訊 按年薪降序
SELECT *,salary*12*(1+IFNULL(commission_pct,0))
FROM employees
ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;
#4、按別名排序
#案例:查詢員工資訊 按年薪升序
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪
FROM employees
ORDER BY 年薪 ASC;
#5、按函式排序
#案例:查詢員工名,並且按名字的長度降序
SELECT LENGTH(last_name),last_name 
FROM employees
ORDER BY LENGTH(last_name) DESC;
#6、按多個欄位排序
#案例:查詢員工資訊,要求先按工資降序,再按employee_id升序
SELECT *
FROM employees
ORDER BY salary DESC,employee_id ASC;

---------------------------------------------------------------------------------
#1.查詢員工的姓名和部門號和年薪,按年薪降序 按姓名升序

SELECT last_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) 年薪
FROM employees
ORDER BY 年薪 DESC,last_name ASC;

#2.選擇工資不在8000到17000的員工的姓名和工資,按工資降序
SELECT last_name,salary
FROM employees

WHERE salary NOT BETWEEN 8000 AND 17000
ORDER BY salary DESC;

#3.查詢郵箱中包含e的員工資訊,並先按郵箱的位元組數降序,再按部門號升序

SELECT *,LENGTH(email)
FROM employees
WHERE email LIKE '%e%'
ORDER BY LENGTH(email) DESC,department_id ASC;

4.mysql基礎4(常見函式查詢):

#進階4:常見函式
/*
概念:類似於sql的方法,將一組邏輯語句封裝在方法體中,對外暴露方法名
好處:1、隱藏了實現細節  2、提高程式碼的重用性
呼叫:select 函式名(實參列表) 【from 表】;
特點:
	①叫什麼(函式名)
	②幹什麼(函式功能)
分類:
	1、單行函式
	如 concat、length、ifnull等
	2、分組函式
	功能:做統計使用,又稱為統計函式、聚合函式、組函式
常見函式:
	一、單行函式
	字元函式:
	length:獲取位元組個數(utf-8一個漢字代表3個位元組,gbk為2個位元組)
	concat
	substr
	instr
	trim
	upper
	lower
	lpad
	rpad
	replace
	數學函式:
	round
	ceil
	floor
	truncate
	mod
	日期函式:
	now
	curdate
	curtime
	year
	month
	monthname
	day
	hour
	minute
	second
	str_to_date
	date_format
	其他函式:
	version
	database
	user
	控制函式
	if
	case
*/
#一、字元函式
#1.length 獲取引數值的位元組個數
SELECT LENGTH('john');
SELECT LENGTH('張三丰hahaha');
SHOW VARIABLES LIKE '%char%'
#2.concat 拼接字串
SELECT CONCAT(last_name,'_',first_name) 姓名 FROM employees;
#3.upper、lower
SELECT UPPER('john');
SELECT LOWER('joHn');
#示例:將姓變大寫,名變小寫,然後拼接
SELECT CONCAT(UPPER(last_name),LOWER(first_name))  姓名 FROM employees;
#4.substr、substring
注意:索引從1開始
#擷取從指定索引處後面所有字元
SELECT SUBSTR('李莫愁愛上了陸展元',7)  out_put; -- 陸展元
#擷取從指定索引處指定字元長度的字元
SELECT SUBSTR('李莫愁愛上了陸展元',1,3) out_put; -- 李莫愁
#案例:姓名中首字元大寫,其他字元小寫然後用_拼接,顯示出來
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2)))  out_put
FROM employees;
#5.instr 返回子串第一次出現的索引,如果找不到返回0
SELECT INSTR('楊不殷六俠悔愛上了殷六俠','殷八俠') AS out_put;
#6.trim
SELECT LENGTH(TRIM('    張翠山    ')) AS out_put;
SELECT TRIM('aa' FROM 'aaaaaaaaa張aaaaaaaaaaaa翠山aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')  AS out_put;
#7.lpad 用指定的字元實現左填充指定長度
SELECT LPAD('殷素素',2,'*') AS out_put;
#8.rpad 用指定的字元實現右填充指定長度
SELECT RPAD('殷素素',12,'ab') AS out_put;
#9.replace 替換
SELECT REPLACE('周芷若周芷若周芷若周芷若張無忌愛上了周芷若','周芷若','趙敏') AS out_put;

#二、數學函式
#round 四捨五入
SELECT ROUND(-1.55);
SELECT ROUND(1.567,2);
#ceil 向上取整,返回>=該引數的最小整數
SELECT CEIL(-1.02);
#floor 向下取整,返回<=該引數的最大整數
SELECT FLOOR(-9.99);
#truncate 截斷(保留幾個小數)
SELECT TRUNCATE(1.69999,1);
#mod取餘(被除數是正就是正,被除數為負就是負數)
/*
mod(a,b) :  a-a/b*b
mod(-10,-3):-10- (-10)/(-3)*(-3)=-1
*/
SELECT MOD(10,-3);
SELECT 10%3;

#三、日期函式
#now 返回當前系統日期+時間
SELECT NOW();
#curdate 返回當前系統日期,不包含時間
SELECT CURDATE();
#curtime 返回當前時間,不包含日期
SELECT CURTIME();
#可以獲取指定的部分,年、月、日、小時、分鐘、秒
SELECT YEAR(NOW()) 年;
SELECT YEAR('1998-1-1') 年;
SELECT  YEAR(hiredate) 年 FROM employees;
SELECT MONTH(NOW()) 月;
# 英文
SELECT MONTHNAME(NOW()) 月;
#str_to_date 將字元通過指定的格式轉換成日期
SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;
#查詢入職日期為1992--4-3的員工資訊
SELECT * FROM employees WHERE hiredate = '1992-4-3';
SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y');
#date_format 將日期轉換成字元
SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS out_put;
#查詢有獎金的員工名和入職日期(xx月/xx日 xx年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %y年') 入職日期
FROM employees
WHERE commission_pct IS NOT NULL;

#四、其他函式
SELECT VERSION();
SELECT DATABASE();
SELECT USER();

#五、流程控制函式
#1.if函式: if else 的效果
SELECT IF(10<5,'大','小');
SELECT last_name,commission_pct,IF(commission_pct IS NULL,'沒獎金,呵呵','有獎金,嘻嘻') 備註
FROM employees;
#2.case函式的使用一: switch case 的效果
/*
sql中
switch(變數或表示式){
	case 常量1:語句1;break;
	...
	default:語句n;break;
}
mysql中
case 要判斷的欄位或表示式
when 常量1 then 要顯示的值1或語句1;
when 常量2 then 要顯示的值2或語句2;
...
else 要顯示的值n或語句n;
end
*/
/*案例:查詢員工的工資,要求
部門號=30,顯示的工資為1.1倍
部門號=40,顯示的工資為1.2倍
部門號=50,顯示的工資為1.3倍
其他部門,顯示的工資為原工資
*/
SELECT salary 原始工資,department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工資
FROM employees;
#3.case 函式的使用二:類似於 多重if
/*
sql中:
if(條件1){
	語句1;
}else if(條件2){
	語句2;
}
...
else{
	語句n;
}
mysql中:
case 
when 條件1 then 要顯示的值1或語句1
when 條件2 then 要顯示的值2或語句2
。。。
else 要顯示的值n或語句n
end
*/
#案例:查詢員工的工資的情況
如果工資>20000,顯示A級別
如果工資>15000,顯示B級別
如果工資>10000,顯示C級別
否則,顯示D級別
SELECT salary,
CASE 
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END AS 工資級別
FROM employees;
-----------------------------------------------------------------------------------
作業:
#1.	顯示系統時間(注:日期+時間)
SELECT NOW();
#2.	查詢員工號,姓名,工資,以及工資提高百分之20%後的結果(new salary)
SELECT employee_id,last_name,salary,salary*1.2 "new salary"
FROM employees;
#3.	將員工的姓名按首字母排序,並寫出姓名的長度(length)
SELECT LENGTH(last_name) 長度,SUBSTR(last_name,1,1) 首字元,last_name
FROM employees
ORDER BY 首字元;
#4.	做一個查詢,產生下面的結果
<last_name> earns <salary> monthly but wants <salary*3>
Dream Salary
King earns 24000 monthly but wants 72000
SELECT CONCAT(last_name,' earns ',salary,' monthly but wants ',salary*3) AS "Dream Salary"
FROM employees
WHERE salary=24000;
#5.	使用case-when,按照下面的條件:
job                  grade
AD_PRES            A
ST_MAN             B
IT_PROG             C
SA_REP              D
ST_CLERK           E
產生下面的結果
Last_name	Job_id	Grade
king	AD_PRES	A
SELECT last_name,job_id AS  job,
CASE job_id
WHEN 'AD_PRES' THEN 'A' 
WHEN 'ST_MAN' THEN 'B' 
WHEN 'IT_PROG' THEN 'C' 
WHEN 'SA_PRE' THEN 'D'
WHEN 'ST_CLERK' THEN 'E'
END AS Grade
FROM employees
WHERE job_id = 'AD_PRES';


select substr(email,1, instr(email, '@') -1) from stuinfo;

5.mysql基礎5(分組函式):

#二、分組函式
/*
功能:用作統計使用,又稱為聚合函式或統計函式或組函式
分類:
sum 求和、avg 平均值、max 最大值 、min 最小值 、count 計算個數
特點:
1、sum、avg一般用於處理數值型
   max、min、count可以處理任何型別
2、以上分組函式都忽略null值
3、可以和distinct搭配實現去重的運算
4、count函式的單獨介紹
一般使用count(*)用作統計行數
5、和分組函式一同查詢的欄位要求是group by後的欄位
*/
#1、簡單 的使用
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT COUNT(salary) FROM employees;
SELECT SUM(salary) 和,AVG(salary) 平均,MAX(salary) 最高,MIN(salary) 最低,COUNT(salary) 個數
FROM employees;
SELECT SUM(salary) 和,ROUND(AVG(salary),2) 平均,MAX(salary) 最高,MIN(salary) 最低,COUNT(salary) 個數
FROM employees;

#2、引數支援哪些型別
SELECT SUM(last_name) ,AVG(last_name) FROM employees;
SELECT SUM(hiredate) ,AVG(hiredate) FROM employees;
SELECT MAX(last_name),MIN(last_name) FROM employees;
SELECT MAX(hiredate),MIN(hiredate) FROM employees;
# 處理非null值
SELECT COUNT(commission_pct) FROM employees;
SELECT COUNT(last_name) FROM employees;

#3、是否忽略null
SELECT SUM(commission_pct) ,AVG(commission_pct),SUM(commission_pct)/35,SUM(commission_pct)/107 FROM employees;
SELECT MAX(commission_pct) ,MIN(commission_pct) FROM employees;
SELECT COUNT(commission_pct) FROM employees;
SELECT commission_pct FROM employees;

#4、和distinct搭配
SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;

#5、count函式的詳細介紹
SELECT COUNT(salary) FROM employees;
SELECT COUNT(*) FROM employees;
SELECT COUNT(1) FROM employees;
效率:
MYISAM儲存引擎下  ,COUNT(*)的效率高
INNODB儲存引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(欄位)要高一些

#6、和分組函式一同查詢的欄位有限制
SELECT AVG(salary),employee_id  FROM employees;

-----------------------------------------------------------------------------------
#1.查詢公司員工工資的最大值,最小值,平均值,總和

SELECT MAX(salary) 最大值,MIN(salary) 最小值,AVG(salary) 平均值,SUM(salary) 和
FROM employees;
#2.查詢員工表中的最大入職時間和最小入職時間的相差天數 (DIFFRENCE)

SELECT MAX(hiredate) 最大,MIN(hiredate) 最小,(MAX(hiredate)-MIN(hiredate))/1000/3600/24 DIFFRENCE
FROM employees;

SELECT DATEDIFF(MAX(hiredate),MIN(hiredate)) DIFFRENCE
FROM employees;

SELECT DATEDIFF('1995-2-7','1995-2-6');

#3.查詢部門編號為90的員工個數

SELECT COUNT(*) FROM employees WHERE department_id = 90;

6.mysql基礎6(分組查詢):

#進階5:分組查詢

/*
語法:

select 查詢列表
from 表
【where 篩選條件】
group by 分組的欄位
【order by 排序的欄位】;

特點:
1、和分組函式一同查詢的欄位必須是group by後出現的欄位 *****

2、篩選分為兩類:分組前篩選和分組後篩選
		針對的表			位置		連線的關鍵字
分組前篩選	原始表				group by前	where
分組後篩選	group by後的結果集    		group by後	having

問題1:分組函式做篩選能不能放在where後面
答:不能

問題2:where——group by——having

一般來講,能用分組前篩選的,儘量使用分組前篩選,提高效率

3、分組可以按單個欄位也可以按多個欄位
4、可以搭配著排序使用

*/

#引入:查詢每個部門的員工個數

SELECT COUNT(*) FROM employees WHERE department_id=90;
#1.簡單的分組

#案例1:查詢每個工種的員工平均工資
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;

#案例2:查詢每個位置的部門個數

SELECT COUNT(*),location_id
FROM departments
GROUP BY location_id;

#2、可以實現分組前的篩選

#案例1:查詢郵箱中包含a字元的 每個部門的最高工資

SELECT MAX(salary),department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;

#案例2:查詢有獎金的每個領導手下員工的平均工資

SELECT AVG(salary),manager_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY manager_id;

#3、分組後篩選

#案例:查詢哪個部門的員工個數>5

#①查詢每個部門的員工個數
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id;

#② 篩選剛才①結果

SELECT COUNT(*),department_id
FROM employees

GROUP BY department_id

HAVING COUNT(*)>5;

#案例2:每個工種有獎金的員工的最高工資>12000的工種編號和最高工資

SELECT job_id,MAX(salary)
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>12000;

#案例3:領導編號>102的每個領導手下的最低工資大於5000的領導編號和最低工資

manager_id>102

SELECT manager_id,MIN(salary)
FROM employees
GROUP BY manager_id
HAVING MIN(salary)>5000;

#4.新增排序

#案例:每個工種有獎金的員工的最高工資>6000的工種編號和最高工資,按最高工資升序

SELECT job_id,MAX(salary) m
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING m>6000
ORDER BY m ;

#5.按多個欄位分組

#案例:查詢每個工種每個部門的最低工資,並按最低工資降序

SELECT MIN(salary),job_id,department_id
FROM employees
GROUP BY department_id,job_id
ORDER BY MIN(salary) DESC;
---------------------------------------------------------------------------------
#1.查詢各job_id的員工工資的最大值,最小值,平均值,總和,並按job_id升序

SELECT MAX(salary),MIN(salary),AVG(salary),SUM(salary),job_id
FROM employees
GROUP BY job_id
ORDER BY job_id;

#2.查詢員工最高工資和最低工資的差距(DIFFERENCE)
SELECT MAX(salary)-MIN(salary) DIFFRENCE
FROM employees;
#3.查詢各個管理者手下員工的最低工資,其中最低工資不能低於6000,沒有管理者的員工不計算在內
SELECT MIN(salary),manager_id
FROM employees
WHERE manager_id IS NOT NULL
GROUP BY manager_id
HAVING MIN(salary)>=6000;

#4.查詢所有部門的編號,員工數量和工資平均值,並按平均工資降序
SELECT department_id,COUNT(*),AVG(salary) a
FROM employees
GROUP BY department_id
ORDER BY a DESC;
#5.選擇具有各個job_id的員工人數
SELECT COUNT(*) 個數,job_id
FROM employees
GROUP BY job_id;

7.mysql基礎7(連線查詢1):

#進階6:連線查詢
/*
含義:又稱多表查詢,當查詢的欄位來自於多個表時,就會用到連線查詢

笛卡爾乘積現象:表1 有m行,表2有n行,結果=m*n行

發生原因:沒有有效的連線條件
如何避免:新增有效的連線條件

分類:
	按年代分類:
	sql92標準:僅僅支援內連線
	sql99標準【推薦】:支援內連線+外連線(左外和右外)+交叉連線

	按功能分類:
		內連線:
			等值連線
			非等值連線
			自連線
		外連線:
			左外連線
			右外連線
			全外連線

		交叉連線

*/

SELECT * FROM beauty;

SELECT * FROM boys;

SELECT NAME,boyName FROM boys,beauty
WHERE beauty.boyfriend_id= boys.id;

#一、sql92標準
#1、等值連線
/*

① 多表等值連線的結果為多表的交集部分
②n表連線,至少需要n-1個連線條件
③ 多表的順序沒有要求
④一般需要為表起別名
⑤可以搭配前面介紹的所有子句使用,比如排序、分組、篩選

*/

#案例1:查詢女神名和對應的男神名
SELECT NAME,boyName 
FROM boys,beauty
WHERE beauty.boyfriend_id= boys.id;

#案例2:查詢員工名和對應的部門名

SELECT last_name,department_name
FROM employees,departments
WHERE employees.`department_id`=departments.`department_id`;

#2、為表起別名
/*
①提高語句的簡潔度
②區分多個重名的欄位

注意:如果為表起了別名,則查詢的欄位就不能使用原來的表名去限定

*/
#查詢員工名、工種號、工種名

SELECT e.last_name,e.job_id,j.job_title
FROM employees  e,jobs j
WHERE e.`job_id`=j.`job_id`;

#3、兩個表的順序是否可以調換

#查詢員工名、工種號、工種名

SELECT e.last_name,e.job_id,j.job_title
FROM jobs j,employees e
WHERE e.`job_id`=j.`job_id`;

#4、可以加篩選

#案例:查詢有獎金的員工名、部門名

SELECT last_name,department_name,commission_pct

FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`commission_pct` IS NOT NULL;

#案例2:查詢城市名中第二個字元為o的部門名和城市名

SELECT department_name,city
FROM departments d,locations l
WHERE d.`location_id` = l.`location_id`
AND city LIKE '_o%';

#5、可以加分組

#案例1:查詢每個城市的部門個數

SELECT COUNT(*) 個數,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY city;

#案例2:查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資
SELECT department_name,d.`manager_id`,MIN(salary)
FROM departments d,employees e
WHERE d.`department_id`=e.`department_id`
AND commission_pct IS NOT NULL
GROUP BY department_name,d.`manager_id`;
#6、可以加排序

#案例:查詢每個工種的工種名和員工的個數,並且按員工個數降序

SELECT job_title,COUNT(*)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;

#7、可以實現三表連線?

#案例:查詢員工名、部門名和所在的城市

SELECT last_name,department_name,city
FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`
AND city LIKE 's%'

ORDER BY department_name DESC;

#2、非等值連線

#案例1:查詢員工的工資和工資級別

SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal`
AND g.`grade_level`='A';

/*
select salary,employee_id from employees;
select * from job_grades;
CREATE TABLE job_grades
(grade_level VARCHAR(3),
 lowest_sal  int,
 highest_sal int);

INSERT INTO job_grades
VALUES ('A', 1000, 2999);

INSERT INTO job_grades
VALUES ('B', 3000, 5999);

INSERT INTO job_grades
VALUES('C', 6000, 9999);

INSERT INTO job_grades
VALUES('D', 10000, 14999);

INSERT INTO job_grades
VALUES('E', 15000, 24999);

INSERT INTO job_grades
VALUES('F', 25000, 40000);

*/

#3、自連線

#案例:查詢 員工名和上級的名稱

SELECT e.employee_id,e.last_name,m.employee_id,m.last_name
FROM employees e,employees m
WHERE e.`manager_id`=m.`employee_id`;
-----------------------------------------------------------------------------------
#1.顯示所有員工的姓名,部門號和部門名稱。
USE myemployees;

SELECT last_name,d.department_id,department_name
FROM employees e,departments d
WHERE e.`department_id` = d.`department_id`;

#2.查詢90號部門員工的job_id和90號部門的location_id

SELECT job_id,location_id
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`department_id`=90;

#3.	選擇所有有獎金的員工的
last_name , department_name , location_id , city

SELECT last_name , department_name , l.location_id , city
FROM employees e,departments d,locations l
WHERE e.department_id = d.department_id
AND d.location_id=l.location_id
AND e.commission_pct IS NOT NULL;

#4.選擇city在Toronto工作的員工的
last_name , job_id , department_id , department_name 

SELECT last_name , job_id , d.department_id , department_name 
FROM employees e,departments d ,locations l
WHERE e.department_id = d.department_id
AND d.location_id=l.location_id
AND city = 'Toronto';

#5.查詢每個工種、每個部門的部門名、工種名和最低工資

SELECT department_name,job_title,MIN(salary) 最低工資
FROM employees e,departments d,jobs j
WHERE e.`department_id`=d.`department_id`
AND e.`job_id`=j.`job_id`
GROUP BY department_name,job_title;

#6.查詢每個國家下的部門個數大於2的國家編號

SELECT country_id,COUNT(*) 部門個數
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY country_id
HAVING 部門個數>2;

#7、選擇指定員工的姓名,員工號,以及他的管理者的姓名和員工號,結果類似於下面的格式
employees	Emp#	manager	Mgr#
kochhar		101	king	100

SELECT e.last_name employees,e.employee_id "Emp#",m.last_name manager,m.employee_id "Mgr#"
FROM employees e,employees m
WHERE e.manager_id = m.employee_i

8.選擇指定員工的姓名,員工號,以及他所管理的員工姓名和員工號,結果類似於下面的格式(非常類似7)
elect e.last_name employees, e.employee_id "Emp#", m.last_name manager, m.employee_id "Mgr#"
from employees e, employees m
where e.employee_id = m.manager_id
and e.last_name = 'Kochhar';

8.mysql基礎8(連線查詢2):

#二、sql99語法(不同年份的語法而已,會用就行)
/*
語法:
	select 查詢列表
	from 表1 別名 【連線型別】
	join 表2 別名 
	on 連線條件
	【where 篩選條件】
	【group by 分組】
	【having 篩選條件】
	【order by 排序列表】

分類:
內連線(★):inner
外連線
	左外(★):left 【outer】
	右外(★):right 【outer】
	全外:full【outer】
交叉連線:cross 

*/

#一)內連線
/*
語法:

select 查詢列表
from 表1 別名
inner join 表2 別名
on 連線條件;

分類:
等值
非等值
自連線

特點:
①新增排序、分組、篩選
②inner可以省略
③ 篩選條件放在where後面,連線條件放在on後面,提高分離性,便於閱讀
④inner join連線和sql92語法中的等值連線效果是一樣的,都是查詢多表的交集

*/

#1、等值連線
#案例1.查詢員工名、部門名

SELECT last_name,department_name
FROM departments d
 JOIN  employees e
ON e.`department_id` = d.`department_id`;

#案例2.查詢名字中包含e的員工名和工種名(新增篩選)
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.`job_id`=  j.`job_id`
WHERE e.`last_name` LIKE '%e%';

#3. 查詢部門個數>3的城市名和部門個數,(新增分組+篩選)

#①查詢每個城市的部門個數
#②在①結果上篩選滿足條件的
SELECT city,COUNT(*) 部門個數
FROM departments d
INNER JOIN locations l
ON d.`location_id`=l.`location_id`
GROUP BY city
HAVING COUNT(*)>3;

#案例4.查詢哪個部門的員工個數>3的部門名和員工個數,並按個數降序(新增排序)

#①查詢每個部門的員工個數
SELECT COUNT(*),department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`
GROUP BY department_name

#② 在①結果上篩選員工個數>3的記錄,並排序

SELECT COUNT(*) 個數,department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`
GROUP BY department_name
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;

#5.查詢員工名、部門名、工種名,並按部門名降序(新增三表連線)

SELECT last_name,department_name,job_title
FROM employees e
INNER JOIN departments d ON e.`department_id`=d.`department_id`
INNER JOIN jobs j ON e.`job_id` = j.`job_id`

ORDER BY department_name DESC;

#二)非等值連線

#查詢員工的工資級別

SELECT salary,grade_level
FROM employees e
 JOIN job_grades g
 ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`;

 #查詢工資級別的個數>20的個數,並且按工資級別降序
 SELECT COUNT(*),grade_level
FROM employees e
 JOIN job_grades g
 ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`
 GROUP BY grade_level
 HAVING COUNT(*)>20
 ORDER BY grade_level DESC;

 #三)自連線

 #查詢員工的名字、上級的名字
 SELECT e.last_name,m.last_name
 FROM employees e
 JOIN employees m
 ON e.`manager_id`= m.`employee_id`;

  #查詢姓名中包含字元k的員工的名字、上級的名字
 SELECT e.last_name,m.last_name
 FROM employees e
 JOIN employees m
 ON e.`manager_id`= m.`employee_id`
 WHERE e.`last_name` LIKE '%k%';

 #二、外連線

 /*
 應用場景:用於查詢一個表中有,另一個表沒有的記錄

 特點:
 1、外連線的查詢結果為主表中的所有記錄
	如果從表中有和它匹配的,則顯示匹配的值
	如果從表中沒有和它匹配的,則顯示null
	外連線查詢結果=內連線結果+主表中有而從表沒有的記錄
 2、左外連線,left join左邊的是主表
    右外連線,right join右邊的是主表
 3、左外和右外交換兩個表的順序,可以實現同樣的效果 
 4、全外連線=內連線的結果+表1中有但表2沒有的+表2中有但表1沒有的
 */
 #引入:查詢男朋友 不在男神表的的女神名

 SELECT * FROM beauty;
 SELECT * FROM boys;

 #左外連線
 SELECT b.*,bo.*
 FROM boys bo
 LEFT OUTER JOIN beauty b
 ON b.`boyfriend_id` = bo.`id`
 WHERE b.`id` IS NULL;

 #案例1:查詢哪個部門沒有員工
 #左外
 SELECT d.*,e.employee_id
 FROM departments d
 LEFT OUTER JOIN employees e
 ON d.`department_id` = e.`department_id`
 WHERE e.`employee_id` IS NULL;

 #右外

  SELECT d.*,e.employee_id
 FROM employees e
 RIGHT OUTER JOIN departments d
 ON d.`department_id` = e.`department_id`
 WHERE e.`employee_id` IS NULL;

 #全外

 USE girls;
 SELECT b.*,bo.*
 FROM beauty b
 FULL OUTER JOIN boys bo
 ON b.`boyfriend_id` = bo.id;

 #交叉連線

 SELECT b.*,bo.*
 FROM beauty b
 CROSS JOIN boys bo;

 #sql92和 sql99pk
 /*
 功能:sql99支援的較多
 可讀性:sql99實現連線條件和篩選條件的分離,可讀性較高
 */
 ----------------------------------------------------------------------------------
 
#一、查詢編號>3的女神的男朋友資訊,如果有則列出詳細,如果沒有,用null填充

SELECT b.id,b.name,bo.*
FROM beauty b
LEFT OUTER JOIN boys bo
ON b.`boyfriend_id` = bo.`id`
WHERE b.`id`>3;
#二、查詢哪個城市沒有部門

SELECT city
FROM departments d
RIGHT OUTER JOIN locations l 
ON d.`location_id`=l.`location_id`
WHERE  d.`department_id` IS NULL;

#三、查詢部門名為SAL或IT的員工資訊

SELECT e.*,d.department_name,d.`department_id`
FROM departments  d
LEFT JOIN employees e
ON d.`department_id` = e.`department_id`
WHERE d.`department_name` IN('SAL','IT');

SELECT * FROM departments
WHERE `department_name` IN('SAL','IT');

9.mysql基礎9(子查詢):

#進階7:子查詢
/*
含義:
出現在其他語句中的select語句,稱為子查詢或內查詢
外部的查詢語句,稱為主查詢或外查詢

分類:
按子查詢出現的位置:
	select後面:
		僅僅支援標量子查詢

	from後面:
		支援表子查詢
	where或having後面:★
		標量子查詢(單行) √
		列子查詢  (多行) √

		行子查詢

	exists後面(相關子查詢)
		表子查詢
按結果集的行列數不同:
	標量子查詢(結果集只有一行一列)
	列子查詢(結果集只有一列多行)
	行子查詢(結果集有一行多列)
	表子查詢(結果集一般為多行多列)
*/

#一、where或having後面
/*
1、標量子查詢(單行子查詢)
2、列子查詢(多行子查詢)

3、行子查詢(多列多行)

特點:
①子查詢放在小括號內
②子查詢一般放在條件的右側
③標量子查詢,一般搭配著單行操作符使用
> < >= <= = <>

列子查詢,一般搭配著多行操作符使用
not int、in、any/some(任意一個)、all(所有)

④子查詢的執行優先於主查詢執行,主查詢的條件用到了子查詢的結果

*/
#1.標量子查詢★

#案例1:誰的工資比 Abel 高?

#①查詢Abel的工資
SELECT salary
FROM employees
WHERE last_name = 'Abel'

#②查詢員工的資訊,滿足 salary>①結果
SELECT *
FROM employees
WHERE salary>(

	SELECT salary
	FROM employees
	WHERE last_name = 'Abel'

);

#案例2:返回job_id與141號員工相同,salary比143號員工多的員工 姓名,job_id 和工資

#①查詢141號員工的job_id
SELECT job_id
FROM employees
WHERE employee_id = 141

#②查詢143號員工的salary
SELECT salary
FROM employees
WHERE employee_id = 143

#③查詢員工的姓名,job_id 和工資,要求job_id=①並且salary>②

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 MIN(salary)
FROM employees

#②查詢last_name,job_id和salary,要求salary=①
SELECT last_name,job_id,salary
FROM employees
WHERE salary=(
	SELECT MIN(salary)
	FROM employees
);

#案例4:查詢最低工資大於50號部門最低工資的部門id和其最低工資

#①查詢50號部門的最低工資
SELECT  MIN(salary)
FROM employees
WHERE department_id = 50

#②查詢每個部門的最低工資

SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id

#③ 在②基礎上篩選,滿足min(salary)>①
SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
	SELECT  MIN(salary)
	FROM employees
	WHERE department_id = 50

);

#非法使用標量子查詢

SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
	SELECT  salary
	FROM employees
	WHERE department_id = 250

);

#2.列子查詢(多行子查詢)★
#案例1:返回location_id是1400或1700的部門中的所有員工姓名

#①查詢location_id是1400或1700的部門編號
SELECT DISTINCT department_id
FROM departments
WHERE location_id IN(1400,1700)

#②查詢員工姓名,要求部門號是①列表中的某一個

SELECT last_name
FROM employees
WHERE department_id  <>ALL(
	SELECT DISTINCT department_id
	FROM departments
	WHERE location_id IN(1400,1700)

);

#案例2:返回其它工種中比job_id為‘IT_PROG’工種任一工資低的員工的員工號、姓名、job_id 以及salary

#①查詢job_id為‘IT_PROG’部門任一工資

SELECT DISTINCT salary
FROM employees
WHERE job_id = 'IT_PROG'

#②查詢員工號、姓名、job_id 以及salary,salary<(①)的任意一個
SELECT last_name,employee_id,job_id,salary
FROM employees
WHERE salary<ANY(
	SELECT DISTINCT salary
	FROM employees
	WHERE job_id = 'IT_PROG'

) AND job_id<>'IT_PROG';

#或
SELECT last_name,employee_id,job_id,salary
FROM employees
WHERE salary<(
	SELECT MAX(salary)
	FROM employees
	WHERE job_id = 'IT_PROG'

) AND job_id<>'IT_PROG';

#案例3:返回其它部門中比job_id為‘IT_PROG’部門所有工資都低的員工   的員工號、姓名、job_id 以及salary

SELECT last_name,employee_id,job_id,salary
FROM employees
WHERE salary<ALL(
	SELECT DISTINCT salary
	FROM employees
	WHERE job_id = 'IT_PROG'

) AND job_id<>'IT_PROG';

#或

SELECT last_name,employee_id,job_id,salary
FROM employees
WHERE salary<(
	SELECT MIN( salary)
	FROM employees
	WHERE job_id = 'IT_PROG'

) AND job_id<>'IT_PROG';

#3、行子查詢(結果集一行多列或多行多列)

#案例:查詢員工編號最小並且工資最高的員工資訊

SELECT * 
FROM employees
WHERE (employee_id,salary)=(
	SELECT MIN(employee_id),MAX(salary)
	FROM employees
);

#①查詢最小的員工編號
SELECT MIN(employee_id)
FROM employees

#②查詢最高工資
SELECT MAX(salary)
FROM employees

#③查詢員工資訊
SELECT *
FROM employees
WHERE employee_id=(
	SELECT MIN(employee_id)
	FROM employees

)AND salary=(
	SELECT MAX(salary)
	FROM employees

);

#二、select後面
/*
僅僅支援標量子查詢
*/

#案例:查詢每個部門的員工個數

SELECT d.*,(

	SELECT COUNT(*)
	FROM employees e
	WHERE e.department_id = d.`department_id`
 ) 個數
 FROM departments d;

 #案例2:查詢員工號=102的部門名

SELECT (
	SELECT department_name,e.department_id
	FROM departments d
	INNER JOIN employees e
	ON d.department_id=e.department_id
	WHERE e.employee_id=102

) 部門名;

#三、from後面
/*
將子查詢結果充當一張表,要求必須起別名
*/

#案例:查詢每個部門的平均工資的工資等級
#①查詢每個部門的平均工資
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id

SELECT * FROM job_grades;

#②連線①的結果集和job_grades表,篩選條件平均工資 between lowest_sal and highest_sal

SELECT  ag_dep.*,g.`grade_level`
FROM (
	SELECT AVG(salary) ag,department_id
	FROM employees
	GROUP BY department_id
) ag_dep
INNER JOIN job_grades g
ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;

#四、exists後面(相關子查詢)

/*
語法:
exists(完整的查詢語句)
結果:
1或0

*/

SELECT EXISTS(SELECT employee_id FROM employees WHERE salary=300000);

#案例1:查詢有員工的部門名

#in
SELECT department_name
FROM departments d
WHERE d.`department_id` IN(
	SELECT department_id
	FROM employees

)

#exists

SELECT department_name
FROM departments d
WHERE EXISTS(
	SELECT *
	FROM employees e
	WHERE d.`department_id`=e.`department_id`

);

#案例2:查詢沒有女朋友的男神資訊

#in
\
SELECT bo.*
FROM boys bo
WHERE bo.id NOT IN(
	SELECT boyfriend_id
	FROM beauty
)

#exists
SELECT bo.*
FROM boys bo
WHERE NOT EXISTS(
	SELECT boyfriend_id
	FROM beauty b
	WHERE bo.`id`=b.`boyfriend_id`
);
---------------------------------------練習-----------------------------------------
#1.	查詢和Zlotkey相同部門的員工姓名和工資

#①查詢Zlotkey的部門
SELECT department_id
FROM employees
WHERE last_name = 'Zlotkey'

#②查詢部門號=①的姓名和工資
SELECT last_name,salary
FROM employees
WHERE department_id = (
	SELECT department_id
	FROM employees
	WHERE last_name = 'Zlotkey'
)

#2.查詢工資比公司平均工資高的員工的員工號,姓名和工資。

#①查詢平均工資
SELECT AVG(salary)
FROM employees

#②查詢工資>①的員工號,姓名和工資。
SELECT last_name,employee_id,salary
FROM employees
WHERE salary>(
	SELECT AVG(salary)
	FROM employees
);

#3.查詢各部門中工資比本部門平均工資高的員工的員工號, 姓名和工資
#①查詢各部門的平均工資
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id

#②連線①結果集和employees表,進行篩選
SELECT employee_id,last_name,salary,e.department_id
FROM employees e
INNER JOIN (
	SELECT AVG(salary) ag,department_id
	FROM employees
	GROUP BY department_id
) ag_dep
ON e.department_id = ag_dep.department_id
WHERE salary>ag_dep.ag ;

#4.	查詢和姓名中包含字母u的員工在相同部門的員工的員工號和姓名
#①查詢姓名中包含字母u的員工的部門
SELECT  DISTINCT department_id
FROM employees
WHERE last_name LIKE '%u%'

#②查詢部門號=①中的任意一個的員工號和姓名
SELECT last_name,employee_id
FROM employees
WHERE department_id IN(
	SELECT  DISTINCT department_id
	FROM employees
	WHERE last_name LIKE '%u%'
);

#5. 查詢在部門的location_id為1700的部門工作的員工的員工號

#①查詢location_id為1700的部門
SELECT DISTINCT department_id
FROM departments 
WHERE location_id  = 1700

#②查詢部門號=①中的任意一個的員工號
SELECT employee_id
FROM employees
WHERE department_id =ANY(
	SELECT DISTINCT department_id
	FROM departments 
	WHERE location_id  = 1700
);
#6.查詢管理者是King的員工姓名和工資

#①查詢姓名為king的員工編號
SELECT employee_id
FROM employees
WHERE last_name  = 'K_ing'

#②查詢哪個員工的manager_id = ①
SELECT last_name,salary
FROM employees
WHERE manager_id IN(
	SELECT employee_id
	FROM employees
	WHERE last_name  = 'K_ing'
);

#7.查詢工資最高的員工的姓名,要求first_name和last_name顯示為一列,列名為 姓.名
#①查詢最高工資
SELECT MAX(salary)
FROM employees

#②查詢工資=①的姓.名
SELECT CONCAT(first_name,last_name) "姓.名"
FROM employees
WHERE salary=(
	SELECT MAX(salary)
	FROM employees
);

10.mysql基礎10(分頁查詢):

#進階8:分頁查詢 ★
/*

應用場景:當要顯示的資料,一頁顯示不全,需要分頁提交sql請求
語法:
	select 查詢列表
	from 表
	【join type join 表2
	on 連線條件
	where 篩選條件
	group by 分組欄位
	having 分組後的篩選
	order by 排序的欄位】
	limit 【offset,】size;

	offset要顯示條目的起始索引(起始索引從0開始)
	size 要顯示的條目個數
特點:
	①limit語句放在查詢語句的最後
	②公式
	要顯示的頁數 page,每頁的條目數size

	select 查詢列表
	from 表
	limit (page-1)*size,size;

	size=10
	page  
	1	0
	2  	10
	3	20

*/
#案例1:查詢前五條員工資訊

SELECT * FROM  employees LIMIT 0,5;
SELECT * FROM  employees LIMIT 5;

#案例2:查詢第11條——第25條
SELECT * FROM  employees LIMIT 10,15;

#案例3:有獎金的員工資訊,並且工資較高的前10名顯示出來
SELECT 
    * 
FROM
    employees 
WHERE commission_pct IS NOT NULL 
ORDER BY salary DESC 
LIMIT 10 ;

11.關於sql中關鍵字執行順序:

select 查詢列表       7
from 表              1
連線型別 join 表2     2
on 連線條件           3
where 篩選條件        4
group by 分組條件     5
having  分組後的篩選   6
order by 排序條件      8
limit 偏移,條目數      9

12.mysql基礎11(子查詢練習題):

# 1. 查詢工資最低的員工資訊: last_name, salary

#①查詢最低的工資
SELECT MIN(salary)
FROM employees

#②查詢last_name,salary,要求salary=①
SELECT last_name,salary
FROM employees
WHERE salary=(
	SELECT MIN(salary)
	FROM employees
);

# 2. 查詢平均工資最低的部門資訊

#方式一:
#①各部門的平均工資
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id
#②查詢①結果上的最低平均工資
SELECT MIN(ag)
FROM (
	SELECT AVG(salary) ag,department_id
	FROM employees
	GROUP BY department_id
) ag_dep

#③查詢哪個部門的平均工資=②

SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary)=(
	SELECT MIN(ag)
	FROM (
		SELECT AVG(salary) ag,department_id
		FROM employees
		GROUP BY department_id
	) ag_dep

);

#④查詢部門資訊

SELECT d.*
FROM departments d
WHERE d.`department_id`=(
	SELECT department_id
	FROM employees
	GROUP BY department_id
	HAVING AVG(salary)=(
		SELECT MIN(ag)
		FROM (
			SELECT AVG(salary) ag,department_id
			FROM employees
			GROUP BY department_id
		) ag_dep

	)

);

#方式二:
#①各部門的平均工資
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id

#②求出最低平均工資的部門編號
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY AVG(salary) 
LIMIT 1;

#③查詢部門資訊
SELECT *
FROM departments
WHERE department_id=(
	SELECT department_id
	FROM employees
	GROUP BY department_id
	ORDER BY AVG(salary) 
	LIMIT 1
);

# 3. 查詢平均工資最低的部門資訊和該部門的平均工資
#①各部門的平均工資
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id
#②求出最低平均工資的部門編號
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id
ORDER BY AVG(salary) 
LIMIT 1;
#③查詢部門資訊
SELECT d.*,ag
FROM departments d
JOIN (
	SELECT AVG(salary) ag,department_id
	FROM employees
	GROUP BY department_id
	ORDER BY AVG(salary) 
	LIMIT 1

) ag_dep
ON d.`department_id`=ag_dep.department_id;

# 4. 查詢平均工資最高的 job 資訊
#①查詢最高的job的平均工資
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id
ORDER BY AVG(salary) DESC
LIMIT 1

#②查詢job資訊
SELECT * 
FROM jobs
WHERE job_id=(
	SELECT job_id
	FROM employees
	GROUP BY job_id
	ORDER BY AVG(salary) DESC
	LIMIT 1

);
# 5. 查詢平均工資高於公司平均工資的部門有哪些?

#①查詢平均工資
SELECT AVG(salary)
FROM employees

#②查詢每個部門的平均工資
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id

#③篩選②結果集,滿足平均工資>①

SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary)>(
	SELECT AVG(salary)
	FROM employees

);

# 6. 查詢出公司中所有 manager 的詳細資訊.
#①查詢所有manager的員工編號
SELECT DISTINCT manager_id
FROM employees

#②查詢詳細資訊,滿足employee_id=①
SELECT *
FROM employees
WHERE employee_id =ANY(
	SELECT DISTINCT manager_id
	FROM employees

);

# 7. 各個部門中 最高工資中最低的那個部門的 最低工資是多少

#①查詢各部門的最高工資中最低的部門編號
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY MAX(salary)
LIMIT 1

#②查詢①結果的那個部門的最低工資

SELECT MIN(salary) ,department_id
FROM employees
WHERE department_id=(
	SELECT department_id
	FROM employees
	GROUP BY department_id
	ORDER BY MAX(salary)
	LIMIT 1

);
# 8. 查詢平均工資最高的部門的 manager 的詳細資訊: last_name, department_id, email, salary
#①查詢平均工資最高的部門編號
SELECT 
    department_id 
FROM
    employees 
GROUP BY department_id 
ORDER BY AVG(salary) DESC 
LIMIT 1 

#②將employees和departments連線查詢,篩選條件是①
    SELECT 
        last_name, d.department_id, email, salary 
    FROM
        employees e 
        INNER JOIN departments d 
            ON d.manager_id = e.employee_id 
    WHERE d.department_id = 
        (SELECT 
            department_id 
        FROM
            employees 
        GROUP BY department_id 
        ORDER BY AVG(salary) DESC 
        LIMIT 1) ;
---------------------------------------------------------------------------
#一、查詢每個專業的學生人數
SELECT majorid,COUNT(*)
FROM student
GROUP BY majorid;

#二、查詢參加考試的學生中,每個學生的平均分、最高分
SELECT AVG(score),MAX(score),studentno
FROM result
GROUP BY studentno;

#三、查詢姓張的每個學生的最低分大於60的學號、姓名
SELECT s.studentno,s.`studentname`,MIN(score)
FROM student s
JOIN result r
ON s.`studentno`=r.`studentno`
WHERE s.`studentname` LIKE '張%'
GROUP BY s.`studentno`
HAVING MIN(score)>60;
#四、查詢每個專業生日在“1988-1-1”後的學生姓名、專業名稱

SELECT m.`majorname`,s.`studentname`
FROM student s
JOIN major m
ON m.`majorid`=s.`majorid`
WHERE DATEDIFF(borndate,'1988-1-1')>0
GROUP BY m.`majorid`;

#五、查詢每個專業的男生人數和女生人數分別是多少

SELECT COUNT(*),sex,majorid
FROM student
GROUP BY sex,majorid;
#六、查詢專業和張翠山一樣的學生的最低分
#①查詢張翠山的專業編號
SELECT majorid
FROM student
WHERE studentname = '張翠山'

#②查詢編號=①的所有學生編號
SELECT studentno
FROM student
WHERE majorid=(
	SELECT majorid
	FROM student
	WHERE studentname = '張翠山'

)
#②查詢最低分
SELECT MIN(score)
FROM result
WHERE studentno IN(

	SELECT studentno
	FROM student
	WHERE majorid=(
		SELECT majorid
		FROM student
		WHERE studentname = '張翠山'

	)
)

#七、查詢大於60分的學生的姓名、密碼、專業名

SELECT studentname,loginpwd,majorname
FROM student s
JOIN major m ON s.majorid=  m.majorid
JOIN result r ON s.studentno=r.studentno
WHERE r.score>60;
#八、按郵箱位數分組,查詢每組的學生個數
SELECT COUNT(*),LENGTH(email)
FROM student
GROUP BY LENGTH(email);
#九、查詢學生名、專業名、分數

SELECT studentname,score,majorname
FROM student s
JOIN major m ON s.majorid=  m.majorid
LEFT JOIN result r ON s.studentno=r.studentno

#十、查詢哪個專業沒有學生,分別用左連線和右連線實現
#左
SELECT m.`majorid`,m.`majorname`,s.`studentno`
FROM major m
LEFT JOIN student s ON m.`majorid` = s.`majorid`
WHERE s.`studentno` IS NULL;

#右
SELECT m.`majorid`,m.`majorname`,s.`studentno`
FROM student s
RIGHT JOIN  major m ON m.`majorid` = s.`majorid`
WHERE s.`studentno` IS NULL;
#十一、查詢沒有成績的學生人數

SELECT COUNT(*)
FROM student s
LEFT JOIN result r ON s.`studentno` = r.`studentno`
WHERE r.`id` IS NULL