DQL語言的學習
一、DQL語言的學習
進階1:基礎查詢
語法select 查詢列表 from 表名;
一般字段名加上着重號,也可以不加
特點:
- 查詢列表可以是:表中的字段、常量值、表達式、函數
- 查詢的結果是一個虛擬的表格
舉例:
1.查詢表中單個字段
selectlast_name
from employees;2.查詢表中多個字段
selectlast_name
,salary from employees;3.查詢表中所有字段
select * from employees;4.查詢常量值
select 100;
select ‘jack’5.查詢表達式
select 100%3;6.查詢函數
select version();//查版本號7.起別名
便於理解
如果要查詢的字段有重名的情況,使用別名可以區分開來
方式一:使用as
select 100 %3 as 結果;
select last_name as 姓, first_name as 名 from employees;
方式二:使用空格
select last_name 姓, first_name 名 from employees;
注意:如果別名中有特殊符號:空格、’#'等,則要給別名加上雙引號或單引號8.去重 distinct
select distinct department_id from employees;9.+號的作用 只有一個作用:運算符
兩個操作數都爲數值型,則做加法運算
一方爲字符型,則試圖將字符型轉換成數值型
如果轉換成功,則繼續做加法運算
如果轉換失敗,則將字符型數值轉換成0
只要其中一方爲null,則結果肯定爲null10.使用concat實現連接字符
注意:只要其中一方爲null,則結果肯定爲null
select concat(‘a’,‘b’,‘c’) as 結果;//如果是數值型也會自動轉爲字符
select concat(last_name,first_name) as 姓名 from employees;//把姓氏名稱拼接成姓名11.ifnull(a,b) 判斷某字段或表達式(a)是否爲null,如果爲null返回指定的值(b),否則返回原來的值
select ifnull(commission_pct,0) as 獎金率, commission_pct from employees;
12.isnull(a)函數,判斷某字段或表達式(a)是否爲null,如果是返回1,否則返回0
進階2:條件查詢
語法: select 查詢列表③ from 表名① where 篩選條件②;
根據篩選條件分類:
- 按條件表達式篩選
- 條件運算符:> < = !=/<> >= <=
- 按邏輯表達式篩選
- 邏輯運算符:and、or、not
- 模糊查詢
- like、between and、in、is null
- like一般和通配符搭配使用,可以判斷字符型或數值型
- %:任意多個組放,包含0個字符
- _:任意單個字符
- \ 轉義字符
- between and:包含臨界值,相當於 1<= x<=2
- in:判斷某字段的值是否屬於in列表中的某一項
- 特點:使用in提高語句簡潔度
- in列表的值類型必須一致或兼容
- is null:
- = 或<> 不能用於判斷null值
- is null 或is not null 僅可以判斷null值,可讀性較高,建議使用
- 安全等於:<=> 不僅可以判斷null值還可以判斷普通類型的值,可讀性較低
舉例:
一、按條件表達式篩選
select * from employees where salary > 12000;二、按邏輯表達式篩選
select last_name, salary, commission_pct from employees where salary>=10000 and salary<=20000;三、模糊查詢
1.like
select * from employees where last_name like ‘%a%’;//查詢員工名中包含字符a的員工信息
select last_name, salary from employees where last_name like ‘__e_a%’;//員工名中第三個字符爲e,第五個字符爲a
select last_name, salary from employees where last_name like ‘__%’;//員工名第二個字爲_的員工名,要用到轉義字符 \2.between and
select * from employees where employee_id between 100 and 120;3.in
select last_name, job_id from employees where job_id = ‘IT_PROT’ or job_id = ‘AD_VP’ job_id = ‘AD_PRES’;//繁瑣
select last_name, job_id from employees where job_id in (‘IT_PROT’,‘AD_VP’,‘AD_PRES’);4.is null
select last_name, commission_pct from employees where commission_pct is null;//查詢沒獎金的
select last_name, commission_pct from employees where commission_pct is not null;//查詢有獎金的
進階3:排序查詢
語法: select 查詢列表③ from 表① [where 篩選條件]② order by 排序列表[asc|desc]④;
特點:
- asc代表的是升序,desc代表的是降序。如果不寫,默認是升序
- order by子句中可以支持單個字段、多個字段、表達式、函數、別名
- order by子句一般是放在查詢語句的最後面,limit子句除外
舉例:
#案例1:查詢員工信息,要求工資從高到低排序
select * from employees order by salary desc;
select * from employees order by salary; #升序#添加篩選條件
#案例2:查詢部門編號>=90的員工信息,按入職時間的先後進行排序
SELECT * FROM employees WHERE department_id >= 90 ORDER BY hiredate ASC;#按表達式排序
#案例3:按年薪的高低顯示員工的信息和年薪
SELECT , salary12*(1+IFNULL(commission_pct,0)) AS 年薪 FROM employees ORDER BY salary12(1+IFNULL(commission_pct,0)) DESC;#按別名排序
#案例4:按年薪的高低顯示員工的信息和年薪
SELECT , salary12*(1+IFNULL(commission_pct,0)) AS 年薪 FROM employees ORDER BY 年薪 DESC;#按函數排序
#案例5:按姓名的長度顯示員工的姓名和工資
SELECT LENGTH(last_name) 字節長度 , last_name, salary FROM employees ORDER BY 字節長度 DESC;#按多個字段排序
#案例6:查詢員工信息,要求先按工資排序,再按員工編號排序
SELECT * FROM employees ORDER BY salary DESC, employee_id ASC;
進階4:常見函數
功能:類似於Java中的方法,將一組邏輯語句封裝在方法體中,對外暴露方法名
好處:隱藏了實現細節、提高了代碼的重用性
調用:select 函數名(實參列表) [from 表];
特點:叫什麼(函數名)、幹什麼(函數功能)
分類:
-
單行函數(傳一個參數,返回一個值)
-
分類
-
字符函數:length、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
-
datediff(‘a’,‘b’):返回日期a與日期b相差多少天
SELECT DATEDIFF(NOW(),‘1999-12-21’);
-
其他函數:version、database、user、password(‘字符’):返回該字符的密碼形式、md5(‘字符’):返回該字符的md5的加密形式
-
控制函數:if、case
-
-
-
分組函數(傳進一組值,返回一個值)
-
功能:做統計使用,又稱爲統計函數、聚合函數
-
分類:
- sum 求和、avg 平均值、max 最大值、min 最小值、count 計算值爲非空的個數
-
特點:
-
sum、avg一般用於處理數值型
max、min、count可以處理任何類型
-
分組函數是否忽略null值
以上函數都忽略null值
-
可以和distinct搭配實現去重的運算
-
count函數的單獨介紹
一般使用count(*)用作統計行數
-
和分組函數一同查詢的字段要求是group by後的字段
-
-
單行函數舉例
#一、字符函數
#1.length() 獲取參數值的字節個數
SELECT LENGTH(‘john’); #4
SELECT LENGTH(‘張三丰hahaha’)#15 漢字要看具體的編碼方式#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))) FROM employees;#5.instr() 返回子串第一次出現的索引,如果找不到返回0
SELECT INSTR(‘楊不悔殷六俠愛上了殷六俠’,‘殷六俠’) AS ‘index’; #4#6.trim() 去除首位指定的字符,默認去除的是空格
SELECT LENGTH(TRIM(’ 張翠花 ')) AS out_put;#三個漢字,字節長9SELECT TRIM(‘a’ FROM ‘aaaaa翠花aaaaaa張aaa’) AS out_put; #翠花aaaaaa張
SELECT TRIM(‘aa’ FROM ‘aaaaa翠花aaaaaa張aaa’) AS out_put; #a翠花aaaaaa張a 因他是按照連續的aa匹配的#7.lpad() 用指定的字符實現左填充指定長度(填充後總長度爲指定的長度)
SELECT LPAD(‘殷素素’,10,’*’) AS out_put; #******殷素素
SELECT LPAD(‘殷素素’,2,’’) AS out_put; #殷素#8.rpad() 用指定的字符實現左填充指定長度(填充後總長度爲指定的長度)
SELECT RPAD(‘殷素素’,12,‘ab’) AS out_put; #殷素素ababababa
SELECT RPAD(‘殷素素’,2,’*’) AS out_put; #殷素#9.replace() 替換
SELECT REPLACE(‘周芷若周芷若張無忌愛上了周芷若’,‘周芷若’,‘趙敏’) AS out_put;
#二、數學函數
#1.round() 四捨五入
SELECT ROUND(1.23); # 1
SELECT ROUND(1.65); # 2
SELECT ROUND(-1.23); # -1
SELECT ROUND(-1.65); # -2
SELECT ROUND(1.567,2); #重載函數,保留兩位小數 1.57#2.ceil() 向上取整 返回>=該參數的最小整數
SELECT CEIL(-1.02); #-1#3.floor() 向下取整,返回<=該參數的最大整數
SELECT FLOOR(-9.99);#-10#4.truncate() 截斷
SELECT TRUNCATE(1.65,1);#1.6 小數點後保留一位,不會產生近位,直接截斷#5.mod() 取餘
#mod(a,b) : a - a/b * b
#mod(-10,-3): -10 - (-10)/(-3) * (-3) = -1
SELECT MOD(10,-3); # 1
SELECT 1 % 3; # 1
#三、日期函數
#1.now 返回當前系統日期+時間
SELECT NOW();#2.curdate 返回當前的日期,不包含時間
SELECT CURDATE();#3.cutrime 返回當前的時間,不包含日期
SELECT CURTIME();#可獲取指定的部分,年、月、日、小時、分鐘、秒
SELECT YEAR(NOW()) 年; #2020
SELECT YEAR(‘1999-12-21’) 年; #1999
SELECT YEAR(hiredate) 年 FROM employees;
SELECT MONTH(NOW()) 月; #3
SELECT MONTHNAME(NOW()) 月; #March#4.str_to_date:將日期格式的字符轉換成指定格式的日期
SELECT STR_TO_DATE(‘1998-3-2’,’%Y-%c-%d’) AS out_put;
#查詢入職日期爲 1992-4-3的員工的信息
SELECT * FROM employees WHERE hiredate = STR_TO_DATE(‘4-3 1992’, ‘%c-%d %Y’);#5.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 的效果if(條件表達式,表達式1,表達式2):如果條件表達式成立,返回表達式1,否則返回表達式2
SELECT IF(10<5,‘大’,‘小’);
SELECT last_name,commission_pct,IF(commission_pct IS NULL,‘沒獎金,呵呵’,‘有獎金,嘻嘻’) 是否有獎金 FROM employees;#2.case函數的使用一: switch case的效果 (判斷等值)
#語法:
case 要判斷的字段或表達式 when 常量1 then 要顯示的值1(或語句1;)
when 常量2 then 要顯示的值2(或語句2;)
else 要顯示值n(或語句n;) (就是Java的default)
…
end
SELECT salary 原始工資, department_id,
CASE department_id
WHEN 30 THEN salary1.1
WHEN 40 THEN salary1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工資
FROM employees;#2.case函數的使用二:類似於 多重if (判斷區間)
#語法:
case
when 常量1 then 要顯示的值1(或語句1;)
when 常量2 then 要顯示的值2(或語句2;)
…
else 要顯示的值n(或語句n;)
end
SELECT salary 工資,
CASE
WHEN salary > 20000 THEN ‘A’
WHEN salary > 15000 THEN ‘B’
WHEN salary > 10000 THEN ‘C’
ELSE ‘D’
END 等級
FROM employees;
分組函數舉例
#1.簡單的使用
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT COUNT(salary) FROM employees;
SELECT SUM(salary) 總和, ROUND(AVG(salary),2) 平均, MAX(salary) 最高, MIN(salary) 最低,COUNT(salary) 個數 FROM employees;#2.參數支持哪些類型
SELECT SUM(hiredate), AVG(hiredate) 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;#4.和distinct搭配
SELECT SUM(DISTINCT salary), SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary) FROM employees;#5.count函數的詳細介紹
SELECT COUNT(salary) FROM employees;
SELECT COUNT() FROM employees; #用來統計行數
SELECT COUNT(‘任意值’) FROM employees; #等於加了一列1,統計1的個數。實際上還是統計行數。參數可以是任意數值
#效率
MYISAM存儲引擎下,count()的效率高
INNODB存儲引擎下,count(*)和count(1)的效率差不多,比count(字段)要高一些#6.和分組函數一同查詢的字段有限制
SELECT AVG(salary),employee_id FROM employees#雖不報錯,但也無意義
進階5:分組查詢
引入:要求查詢每個部門的平均工資
可以使用group by子句將表中的數據分成若干組
語法:
SELECT 分組函數,列(要求出現再(GROUP by的後面)
FROM 表
[WHERE 篩選條件]
GROUP BY 分組的列表
[ORDER BY 子句]
注意:查詢列表必須特殊,要求是分組函數和group by後出現的字段
特點:
-
1.分組查詢中的篩選條件分爲兩類
數據源 位置 關鍵字 分組前篩選 原始表 group by子句的前面 where 分組後篩選 分組後的結果集 group by子句的後面 having - 分組函數做條件肯定放在having子句中
-
要想實現一行一列的結果集與多行一列的結果集依次比較,可以寫在having裏
- 能用分組前篩選的,就優先考慮使用分組前篩選,考慮性能問題
#案例1:查詢每個工種的最高工資
SELECT MAX(salary),job_id FROM employees GROUP BY job_id;#案例2:查詢每個位置上的部門個數
SELECT COUNT(*),location_id FROM departments GROUP BY location_id;#添加分組前篩選條件
#案例1:查詢郵箱中包含a字符的,每個部門的平均工資
SELECT email, department_id, AVG(salary) FROM employees WHERE email LIKE ‘%a%’ GROUP BY department_id;
#案例2:查詢有獎金的每個領導手下員工的最高工資
SELECT MAX(salary), manager_id FROM employees WHERE commission_pct IS NOT NULL GROUP BY manager_id;#添加分組後的篩選條件
#案例1:哪個部門的員工個數>2
#①查詢每個部門的員工個數
SELECT COUNT(),department_id
FROM employees
GROUP BY department_id;
#②根據①的結果進行篩選,查詢哪個部門的員工個數>2 這是分組後的篩選,所以要寫在having裏
SELECT COUNT(),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2;#案例2:查詢每個工種有獎金的員工的最高工資>12000的工種編號和最高工資
#①查詢每個工種有獎金的員工的最高工資
SELECT MAX(salary),job_id
FROM employees
GROUP BY job_id;
#②根據①的結果繼續篩選,最高工資>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的領導編號是哪個,以及其最低工資
#①查詢每個領導手下的員工固定最低工資
SELECT MIN(salary),manager_id
FROM employees
GROUP BY manager_id;
#②在①的基礎上查出領導編號>102
SELECT MIN(salary), manager_id
FROM employees
WHERE manager_id > 102
GROUP BY manager_id
#③添加條件:最低工資>5000
SELECT MIN(salary), manager_id
FROM employees
WHERE manager_id > 102
GROUP BY manager_id
HAVING MIN(salary) > 5000;
- 2.group by子句支持單個字段分組,多個字段分組(多個字段之間用逗號隔開沒有順序要求),表達式或函數(用的較少)
- 3.也可以添加排序(排序放在整個分組查詢的最後)
#添加分組後的篩選條件
#案例1:哪個部門的員工個數>2
#①查詢每個部門的員工個數
SELECT COUNT(),department_id
FROM employees
GROUP BY department_id;
#②根據①的結果進行篩選,查詢哪個部門的員工個數>2 這是分組後的篩選,所以要寫在having裏
SELECT COUNT(),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2;
#案例2:查詢每個工種有獎金的員工的最高工資>12000的工種編號和最高工資
#①查詢每個工種有獎金的員工的最高工資
SELECT MAX(salary),job_id
FROM employees
GROUP BY job_id;
#②根據①的結果繼續篩選,最高工資>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的領導編號是哪個,以及其最低工資
#①查詢每個領導手下的員工固定最低工資
SELECT MIN(salary),manager_id
FROM employees
GROUP BY manager_id;
#②在①的基礎上查出領導編號>102
SELECT MIN(salary), manager_id
FROM employees
WHERE manager_id > 102
GROUP BY manager_id
#③添加條件:最低工資>5000
SELECT MIN(salary), manager_id
FROM employees
WHERE manager_id > 102
GROUP BY manager_id
HAVING MIN(salary) > 5000;#按表達式或函數分組
#案例:按員工姓名的長度分組,查詢每一組的員工的個數,篩選員工個數>5的有哪些
#①查詢每個長度的員工個數
SELECT COUNT() ,LENGTH(last_name) len_name
FROM employees
GROUP BY LENGTH(last_name);
#②添加篩選條件
SELECT COUNT() ,LENGTH(last_name) len_name
FROM employees
GROUP BY len_name #length(last_name)
HAVING COUNT(*)>5;#按多個字段分組
#案例:查詢每個部門每個工種的員工的平均工資
SELECT AVG(salary),department_id,job_id
FROM employees
GROUP BY department_id,job_id;#添加排序
#案例:查詢每個部門每個工種的員工的平均工資,並且按平均工資的高低顯示
SELECT AVG(salary),job_id,department_id
FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id, job_id
HAVING AVG(salary) >10000
ORDER BY AVG(salary) DESC;
進階6:連接查詢
含義:又稱多表查詢,當查詢的字段來自多個表時,就會用到連接查詢
笛卡爾乘積現象:表1有m行,表2有n行,結果=m*n行
發生原因:沒有有效的連接條件
如何避免:添加有效的來連接條件
分類:
- 內連接 inner
- 等值連接
- 多表等值連接的結果爲多表的交集部分
- n表連接,至少需要n-1個連接條件
- 多表的順序沒有要求
- 一般需要爲多表起別名
- 可以搭配前面介紹的所有的子句使用,比如排序、分組、篩選
- 非等值連接
- 自連接
- 等值連接
- 外連接
- 左外連接 left[outer]
- 右外連接 right[outer]
- 全外連接 full[outer]
- 交叉連接 cross(其實就是笛卡兒積)
內連接(sql92語法)
等值連接
語法:
select 查詢列表
from 表1 別名,表2 別名
where 表1.key = 表2.key
[and 篩選條件]
[group by 分組字段]
[having 分組後的篩選]
[order by 排序字段]
示例:
#1、等值連接(連接條件是等於號)
#案例1:查詢員工名和對應的部門名
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、可以篩選嗎
#案例1:查詢有獎金的員工名、部門名
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%’;#4、可以加分組嗎?
#案例1:查詢每個城市的部門個數
SELECT COUNT(*) 個數,city
FROM departments d, locations l
WHERE d.location_id
= l.location_id
GROUP BY city;
#案例2:查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資
SELECT d.manager_id,commission_pct,department_name,MIN(salary)
FROM employees e, departments d
WHERE e.department_id
= d.department_id
AND commission_pct IS NOT NULL
GROUP BY department_name,d.manager_id;#5、可以加排序?
#可以
非等值連接
#非等值連接
#案例:查詢員工的工資和工資級別
SELECT salary,grade_level
FROM employees e, job_grades g
WHERE salary BETWEEN q.lowest_sal AND q.highest_sal;
自連接
#自連接
#案例:查找員工名和領導的名稱
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語法)
語法:
select 查詢列表
from 表1 別名
【inner】join 表2 別名 on 連接條件
where 篩選條件
group by 分組列表
having 分組後的篩選
order by 排序列表
limit 子句
from 表1 別名
【inner】 join 表2 別名
on 連接條件;
特點:
- 添加排序、分組、篩選
- inner可以省略
- 篩選條件放在where後面,連接條件放在on後面,提高分離性,便於閱讀
- inner join連接和sql92語法中的等值連接效果是一樣的,都是查詢多表的交集
等值連接
#查詢員工名、部門名
SELECT last_name,department_name
FROM departments d
INNER JOIN employees e
ON e.department_id
= d.department_id
#查詢名字中包含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%’;#查詢員工名、部門名、工種名,並按部門名降序
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;
外連接(sql99語法)
應用場景:用於查詢一個表中有,另一個表沒有的記錄
語法:
select 查詢列表
from 表1 別名
left|right|full【outer】join 表2 別名 on 連接條件
where 篩選條件
group by 分組列表
having 分組後的篩選
order by 排序列表
limit 子句
特點:
-
外連接的查詢結果爲主表中的所有記錄,如果從表中和他匹配的,則顯示匹配的值,如果從表中沒有和它匹配的,則顯示null,外連接查詢結果=內連接結果+主表中有而從表中沒有的記錄
-
左外連接,left join左邊的是主表
右外連接,right join右邊的是主表
-
左外和右外交換兩個表的順序,可以實現同樣的效果
-
一般來說你要查詢的主要信息在那個表,那個表就設置爲主表
-
全外連接 = 內連接的結果 + 表1中有但表2沒有的 + 表2中有但表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;
進階7:子查詢
含義:嵌套在其他語句中的select語句,稱爲子查詢或內查詢
外部的查詢語句,稱爲主查詢或外查詢
分類:
- 按子查詢出現的位置:
- select後面
- 僅僅支持標量子查詢
- from後面
- 支持表子查詢
- where或having後面 ★
- 標量子查詢(單行)
- 列子查詢(多行)
- 行子查詢(用的較少)
- exists後面(又稱相關子查詢)
- 表子查詢
- select後面
- 按結果集的行列數不同:
- 標量子查詢(結果集只有一行一列)
- 列子查詢(結果集只有一列多行)
- 行子查詢(結果集有一行多列)
- 表子查詢(結果集一般爲多行多列)
一、where或having後面
1.標量子查詢(單行子查詢)
2.列子查詢(單列子查詢)
3.行子查詢(多列多行)
特點:
-
子查詢放在小括號內
-
子查詢一般放在條件的右側
-
標量子查詢,一般搭配着單行操作符使用:> < >= <= = <>
列子查詢:一般搭配着多行操作符使用: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)
FROM employees
GROUP BY department_id
#③在②基礎上篩選,滿足min(salary)>①
SELECT department_id, MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary) > (
SELECT MIN(salary)
FROM employees
WHERE department_id = 50
);#非法使用標量子查詢
SELECT department_id, MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary) > ( # 單行操作符>一般搭配標量子查詢
#子查詢的結果是多行的
SELECT salary
FROM employees
WHERE department_id = 50
);
2.列子查詢(多行子查詢)
返回多行
使用多行比較操作符
-
IN / NOT IN : 等於(不等於)列表中的任意一個
-
ANY|SOME :和子查詢返回的某一個值比較(用的少)
a > any(15,3,33,42):代表a大於這四個數的任意一個值就行
可以用 a > min(15,3,33,42)語句代替
-
ALL :和子查詢返回的所有值比較
-
any和all都可用min或max代替
#列子查詢(多行子查詢)
#案例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 IN (
SELECT DISTINCT department_id
FROM
departments
WHERE location_id IN (1400,1700)
);
#或 這裏IN也等價 =ANY (只有在結果集中比較才能等價)
SELECT last_name
FROM employees
WHERE department_id =ANY (
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’;#案例2:返回其他工種中比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 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 *
FROM employees
WHERE (employee_id,salary) = (
SELECT MIN(employee_id),MAX(salary)
FROM employees
);
二、select後面
#案例:查詢每個部門的員工個數
SELECT d.* , (
SELECT COUNT(*)
FROM employees e
WHERE d.department_id
= e.department_id
) 個數
FROM departments d;
三、from後面
將子查詢結果充當一張表,要求必須起別名
四、exits後面(相關子查詢)
語法:exists(完整的查詢語句)
結果:1或0(查詢的結果是否有結果)
SELECT EXISTS(SELECT employee_id FROM employees) #1
SELECT EXISTS(SELECT employee_id FROM employees WHERE salary = 3000000) #0
進階8:分頁查詢
應用場景:當要顯示的數據,一頁顯示不全,需要分頁提交sql請求
語法:
select 查詢列表 ⑦
from 表 ①
【連接類型(inner…) 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;
案例:
#案例1:查詢前五條員工信息
SELECT * FROM employees LIMIT 0,5;
SELECT * FROM employees LIMIT 5; # 如果從第一條開始可以省略offset#案例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;
進階9 :聯合查詢
union:聯合、合併:將多條查詢語句的結果合併成一個結果
語法:
查詢語句1
union
查詢語句2
union
……
應用場景:當查詢的結果來自多個表,且這多個表沒有直接的連接關係時,但查詢的信息一直時,推薦使用聯合查詢
特點:
- 要求多條查詢語句的查詢的列數是一致的
- 要求多條查詢語句的查詢的每一列的類型和順序最好一致
- union關鍵字默認去重,如果使用union all 可以包含重複項
#聯合查詢
#引入:查出部門編號>90或郵箱包含a的員工信息
SELECT * FROM employees WHERE email LIKE ‘%a%’ OR department_id > 90;
#或者
SELECT * FROM employees WHERE email LIKE ‘%a%’
UNION
SELECT * FROM employees WHERE department_id>90;#union all
SELECT id,cname FROM t_ca WHERE csex=‘男’
UNION ALL
SELECT t_id,tname FROM t_ua WHERE tGender=‘male’;