1. 程式人生 > 其它 >MySQL基礎:基礎查詢

MySQL基礎:基礎查詢

DQL語言:資料查詢語言

3.1 基礎查詢

語法

select 查詢列表
from 表名;

特點

查詢列表可以是欄位、常量、表示式、函式,也可以是多個
查詢結果是一個虛擬表

示例

1、查詢單個欄位
select 欄位名 from 表名;

2、查詢多個欄位
select 欄位名,欄位名 from 表名;

3、查詢所有欄位
select * from 表名

4、查詢常量
select 常量值;
注意:字元型和日期型的常量值必須用單引號引起來,數值型不需要

5、查詢函式
select 函式名(實參列表);

6、查詢表示式
select 100/1234;

7、起別名
①as
②空格

8、去重
select distinct 欄位名 from 表名;

9、+
作用:做加法運算
select 數值+數值; 直接運算
select 字元+數值;先試圖將字元轉換成數值,如果轉換成功,則繼續運算;否則轉換成0,再做運算
select null+值;結果都為null

10、【補充】concat函式
功能:拼接字元
select concat(字元1,字元2,字元3,...);

11、【補充】ifnull函式
功能:判斷某欄位或表示式是否為null,如果為null 返回指定的值,否則返回原本的值
select ifnull(commission_pct,0) from employees;

12、【補充】isnull函式
功能:判斷某欄位或表示式是否為null,如果是,則返回1,否則返回0

基礎查詢的示例:

#進階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.+號的作用

/*

java中的+號:
①運算子,兩個運算元都為數值型
②連線符,只要有一個運算元為字串

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;

3.2 條件查詢

語法

select 查詢列表
from 表名
where 篩選條件

篩選條件的分類

1、簡單條件運算子
> < = <> != >= <=    <=>安全等於

2、邏輯運算子
 && and
  || or
  !  not
  
3、模糊查詢
 like:一般搭配萬用字元使用,可以判斷字元型或數值型
 萬用字元:%任意多個字元,_任意單個字元

between and
in
is null /is not null:用於判斷null值

is null PK <=>
			普通型別的數值	null值		可讀性
is null		×			√		√
<=>		√			√		×

條件查詢的示例

#進階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.3 排序查詢

語法

select 查詢列表
from 表
where 篩選條件
order by 排序列表 【asc}desc】

特點

asc :升序,如果不寫預設升序
   desc:降序

排序列表 支援 單個欄位、多個欄位、函式、表示式、別名

order by的位置一般放在查詢語句的最後(除limit語句之外)

3.4 常見函式

概述

功能:類似於java中的方法
好處:提高重用性和隱藏實現細節
呼叫:select 函式名(實參列表);

單行函式

1、字元函式
  concat:連線
  substr:擷取子串
  upper:變大寫
  lower:變小寫
  replace:替換
  length:獲取位元組長度
  trim:去前後空格
  lpad:左填充
  rpad:右填充
  instr:獲取子串第一次出現的索引
  
2、數學函式
  ceil:向上取整
  round:四捨五入
  mod:取模
  floor:向下取整
  truncate:截斷
  rand:獲取隨機數,返回0-1之間的小數

3、日期函式
  now:返回當前日期+時間
  year:返回年
  month:返回月
  day:返回日
  date_format:將日期轉換成字元
  curdate:返回當前日期
  str_to_date:將字元轉換成日期
  curtime:返回當前時間
  hour:小時
  minute:分鐘
  second:秒
  datediff:返回兩個日期相差的天數
  monthname:以英文形式返回月


4、其他函式
  version 當前資料庫伺服器的版本
  database 當前開啟的資料庫
  user當前使用者
  password('字元'):返回該字元的密碼形式
  md5('字元'):返回該字元的md5加密形式


5、流程控制函式
  ①if(條件表示式,表示式1,表示式2):如果條件表示式成立,返回表示式1,否則返回表示式2
  ②case情況1
  case 變數或表示式或欄位
  when 常量1 then 值1
  when 常量2 then 值2
  ...
  else 值n
  end
  ③case情況2
  case 
  when 條件1 then 值1
  when 條件2 then 值2
  ...
  else 值n
  end

單行函式的示例:

#進階4:常見函式

/*

概念:類似於java的方法,將一組邏輯語句封裝在方法體中,對外暴露方法名
好處:1、隱藏了實現細節  2、提高程式碼的重用性
呼叫:select 函式名(實參列表) 【from 表】;
特點:
	①叫什麼(函式名)
	②幹什麼(函式功能)

分類:
	1、單行函式
	如 concat、length、ifnull等
	2、分組函式
	
	功能:做統計使用,又稱為統計函式、聚合函式、組函式
	
常見函式:
	一、單行函式
	字元函式:【mysql中字元下標從1開始】
	length:獲取位元組個數(utf-8一個漢字代表3個位元組,gbk為2個位元組)
	concat:欄位、字元連線
	substr:字串擷取,三個引數(截什麼,從哪裡開始,截幾個)
	instr :返回子串第一次出現的索引,如果找不到返回0
	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 :檢視mysql版本號
	database :檢視資料庫
	user	:檢視當前使用者
	控制函式
	if: 三個引數,類似三元表示式
	case:多種情況,類似switch 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 的效果

/*
java中
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
/*
java中:
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、分類
 max 最大值
 min 最小值
 sum 和
 avg 平均值
 count 計算個數

 2、特點

 ①語法
 select max(欄位) from 表名;

 ②支援的型別
 sum和avg一般用於處理數值型
 max、min、count可以處理任何資料型別

 ③以上分組函式都忽略null
 ④都可以搭配distinct使用,實現去重的統計
 select sum(distinct 欄位) from 表;
 ⑤count函式
 count(欄位):統計該欄位非空值的個數
 count(*):統計結果集的行數
 案例:查詢每個部門的員工個數
 1 xx    10
 2 dd    20
 3 mm    20
 4 aa    40
 5 hh    40

 count(1):統計結果集的行數

 效率上:
 MyISAM儲存引擎,count(*)最高
 InnoDB儲存引擎,count(*)和count(1)效率>count(欄位)

 ⑥ 和分組函式一同查詢的欄位,要求是group by後出現的欄位

分組函式例項

#二、分組函式
/*
功能:用作統計使用,又稱為聚合函式或統計函式或組函式

分類:
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;

SELECT COUNT(commission_pct) FROM employees;
SELECT COUNT(last_name) FROM employees;

#3、SUM、AVG等會忽略null,因為執行結果沒有null,null+任何值都為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;

3.5 分組查詢

語法

select 分組函式,分組後的欄位
from 表
【where 篩選條件】
group by 分組的欄位
【having 分組後的篩選】
【order by 排序列表】

特點

		使用關鍵字		篩選的表	位置
		分組前篩選		where		原始表			group by的前面
  		分組後篩選		having		分組後的結果	  group by 的後面

分組函式示例

#二、分組函式
/*
功能:用作統計使用,又稱為聚合函式或統計函式或組函式

分類:
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;

SELECT COUNT(commission_pct) FROM employees;
SELECT COUNT(last_name) FROM employees;

#3、SUM、AVG等會忽略null,因為執行結果沒有null,null+任何值都為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;

分組查詢示例


#進階5:分組查詢,當條件在另一個表中就需要分組查詢group by

/*
語法:

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;

3.6 連線查詢

含義

當查詢中涉及到了多個表的欄位,需要使用多表連線
select 欄位1,欄位2
from 表1,表2,...;

笛卡爾乘積:當查詢多個表時,沒有新增有效的連線條件,導致多個表所有行實現完全連線
如何解決:新增有效的連線條件

分類

按年代分類:
  	sql92:相當於只有sql99的內連線部分
  		等值
  		非等值
  		自連線
	也支援一部分外連線(用於oracle、sqlserver,mysql不支援)
	
	sql99【推薦使用】
        內連線
            等值
            非等值
            自連線
        外連線
            左外
            右外
            全外(mysql不支援)
        交叉連線

SQL 92語法

 1、等值連線
  語法:
  	select 查詢列表
  	from 表1 別名,表2 別名
  	where 表1.key=表2.key
  	【and 篩選條件】
  	【group by 分組欄位】
  	【having 分組後的篩選】
  	【order by 排序欄位】

  特點:
  	① 一般為表起別名
  	②多表的順序可以調換
  	③n表連線至少需要n-1個連線條件
  	④等值連線的結果是多表的交集部分


  2、非等值連線
  語法:
  	select 查詢列表
  	from 表1 別名,表2 別名
  	where 非等值的連線條件
  	【and 篩選條件】
  	【group by 分組欄位】
  	【having 分組後的篩選】
  	【order by 排序欄位】
  	
  3、自連線【同一個表拆分成多個表】
  語法:
  	select 查詢列表
  	from 表 別名1,表 別名2
  	where 等值的連線條件
  	【and 篩選條件】
  	【group by 分組欄位】
  	【having 分組後的篩選】
  	【order by 排序欄位】

SQL 99語法

1、內連線
  語法:
  select 查詢列表
  from 表1 別名
  【inner】 join 表2 別名 on 連線條件
  where 篩選條件
  group by 分組列表
  having 分組後的篩選
  order by 排序列表
  limit 子句;

  特點:
  ①表的順序可以調換
  ②內連線的結果=多表的交集
  ③n表連線至少需要n-1個連線條件

  分類:
  等值連線
  非等值連線
  自連線

  2、外連線
  語法:
  select 查詢列表
  from 表1 別名
  left|right|full【outer】 join 表2 別名 on 連線條件
  where 篩選條件
  group by 分組列表
  having 分組後的篩選
  order by 排序列表
  limit 子句;
  特點:
  ①查詢的結果=主表中所有的行,如果從表和它匹配的將顯示匹配行,如果從表沒有匹配的則顯示null
  ②left join 左邊的就是主表,right join 右邊的就是主表
    full join 兩邊都是主表
  ③一般用於查詢除了交集部分的剩餘的不匹配的行

  3、交叉連線

  語法:
  select 查詢列表
  from 表1 別名
  cross join 表2 別名;

  特點:
  類似於笛卡爾乘積

sql92語法連線查詢示例:(不推薦)

#進階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`;

sql99語法連線查詢示例:(推薦)

#二、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.7 子查詢

含義

巢狀在其他語句內部的select語句稱為子查詢或內查詢,
外面的語句可以是insert、update、delete、select等,一般select作為外面語句較多
外面如果為select語句,則此語句稱為外查詢或主查詢

分類

1、按出現位置
select後面:
		僅僅支援標量子查詢
from後面:
		表子查詢
where或having後面:
		標量子查詢
		列子查詢
		行子查詢
exists後面:
		標量子查詢
		列子查詢
		行子查詢
		表子查詢

2、按結果集的行列
標量子查詢(單行子查詢):結果集為一行一列
列子查詢(多行子查詢):結果集為多行一列
行子查詢:結果集為多行多列
表子查詢:結果集為多行多列

示例

 where或having後面
  1、標量子查詢
  案例:查詢最低工資的員工姓名和工資
  ①最低工資
  select min(salary) from employees

  ②查詢員工的姓名和工資,要求工資=①
  select last_name,salary
  from employees
  where salary=(
  	select min(salary) from employees
  );

  2、列子查詢
  案例:查詢所有是領導的員工姓名
  ①查詢所有員工的 manager_id
  select manager_id
  from employees

  ②查詢姓名,employee_id屬於①列表的一個
  select last_name
  from employees
  where employee_id in(
  	select manager_id
  	from employees
  );

3.8 分頁查詢

應用場景

當要查詢的條目數太多,一頁顯示不全

語法

select 查詢列表
from 表
limit 【offset,】size;
注意:
offset代表的是起始的條目索引,預設從0卡死
size代表的是顯示的條目數

公式:
假如要顯示的頁數為page,每一頁條目數為size
select 查詢列表
from 表
limit (page-1)*size,size;

3.9 聯合查詢

含義

union:合併、聯合,將多次查詢結果合併成一個結果
二、語法
查詢語句1
union 【all】
查詢語句2
union 【all】
...

意義

將一條比較複雜的查詢語句拆分成多條語句
適用於查詢多個表的時候,查詢的列基本是一致

特點

要求多條查詢語句的查詢列數必須一致
要求多條查詢語句的查詢的各列型別、順序最好一致
union 去重,union all包含重複項

3.10 查詢總結

語法:

​ select 查詢列表 ⑦
​ from 表1 別名 ①
​ 連線型別 join 表2 ②
​ on 連線條件 ③
​ where 篩選 ④
​ group by 分組列表 ⑤
​ having 篩選 ⑥
​ order by排序列表 ⑧
​ limit 起始條目索引,條目數; ⑨