sql查詢總結
數據庫建表sql和本文md文檔在如下地址:
鏈接:https://pan.baidu.com/s/1pheKTfktS-9Hf141FwJM3w
提取碼:th31
文章目錄
一、基礎查詢
1. 基礎查詢語法
1. 查詢表中的單個字
SELECT last_name
FROM employees`
2.查詢表中的多個字段
SELECT last_name,salary,email
FROM employees;
3.查詢表中的所有字段
SELECT *
FROM employees;
4.查詢常量值
SELECT 100;
5.查詢表達式
SELECT 100%98;
6.查詢函數
SELECT VERSION();
2.起別名(AS,或者空格)
SELECT 100%98 AS 結果
SELECT last_name AS 姓,first_name AS 名
FROM employees;
3.去重(distinct)
SELECT DISTINCT department_id
FROM employees;
4.+號的作用(+號只能計算數字,concat纔是拼接字符串)
- 案例:查詢員工名和姓連接成一個字段,並顯示爲 姓名
SELECT CONCAT('a','b','c') AS 結果;
SELECT CONCAT(last_name,first_name) AS 姓名 FROM employees;·
判空 IFNull(str1,str2):如果str1==空,則取str2
SELECT CONCAT(last_name,'老王',first_name,IFNULL(department_id,'我是空')) AS output FROM employees;`
5.基礎查詢小案例
#1. 下面的語句是否可以執行成功
SELECT last_name , job_id , salary AS sal
FROM employees;
#2.下面的語句是否可以執行成功
SELECT * FROM employees;
#3.找出下面語句中的錯誤
SELECT employee_id , last_name,
salary * 12 AS "ANNUAL SALARY"
FROM employees;
#4.顯示錶departments的結構,並查詢其中的全部數據
DESC departments;
DESC departments;
SELECT * FROM `departments`;
#5.顯示出表employees中的全部job_id(不能重複)
SELECT DISTINCT(job_id) FROM employees;
#6.顯示出表employees的全部列,各個列之間用逗號連接,列頭顯示成OUT_PUT
SELECT CONCAT(employee_id,',',first_name,',',last_name,',',email,',',IFNULL(commission_pct,0)) FROM employees;
二、條件查詢
1.按條件表達式篩選
> < = != <> >= <=
#案例1:查詢工資>12000的員工信息
SELECT *
FROM employees
WHERE salary>12000;
#案例2:查詢部門編號不等於90號的員工名和部門編號
SELECT first_name,department_id
FROM employees
WHERE department_id != 90;
2.按邏輯表達式篩選
and or not
#案例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;
3.模糊查詢
1.like
like一般搭配通配符使用
通配符:_(只佔一個字符)或者&(可佔多個字符)
#案例1:查詢員工名中包含字符a的員工信息
SELECT *
FROM employees
WHERE first_name LIKE '%a%';
#案例2:查詢員工名中第三個字符爲e,第五個字符爲a的員工名和工資
SELECT first_name,salary
FROM employees
WHERE first_name LIKE '__e_a';
#案例3:查詢員工名中第二個字符爲_的員工名
SELECT first_name
FROM employees
WHERE first_name LIKE '_$_%' ESCAPE '$';
2.between 1 and100
bewttem 1 and 10
#案例1:查詢員工編號在100到120之間的員工信息
SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120;
不在100-120之間:NOT BETWEEN 100 AND 120;
3.in
in
#案例:查詢員工的工種編號是 IT_PROG、AD_VP、AD_PRES中的一個員工名和工種編號
SELECT first_name,job_id FROM employees WHERE job_id IN ('IT_PROG','AD_VP','AD_PRES');
4. is null(==null)和is not null(!=null)
is null 和 is not null
#案例1:查詢沒有獎金的員工名和獎金率
SELECT first_name,commission_pct FROM employees WHERE commission_pct IS NULL;
#案例1:查詢有獎金的員工名和獎金率
SELECT first_name,commission_pct FROM employees WHERE commission_pct IS NOT NULL;
5.案例練習
#1.查詢工資大於 12000 的員工姓名和工資
SELECT first_name,salary
FROM employees
WHERE salary>12000;
#2.查詢員工號爲176的員工姓名的部門號和年薪
SELECT first_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM employees
WHERE employee_id =176;
#3.選擇工資不在5000到12000的員工姓名和工資
SELECT first_name,salary
FROM employees
WHERE salary NOT BETWEEN 5000 AND 12000;
#4.選擇在20或50號部門工作的員工姓名和部門號
SELECT first_name,department_id
FROM employees
WHERE department_id =20 OR department_id =50;
#5.選擇公司中沒有管理者的員工姓名和job_id
SELECT first_name,job_id
FROM employees
WHERE manager_id IS NULL;
#6.選擇公司中有獎金的員工姓名,工資和獎金級別
SELECT first_name,salary
FROM employees
WHERE commission_pct IS NOT NULL;
#7.選擇員工姓名的第三個字母是a的員工姓名
SELECT first_name
FROM employees
WHERE first_name LIKE '__a%';
#8.選擇姓名中有字母a和e的員工姓名
SELECT first_name
FROM employees
WHERE first_name LIKE '%a%' AND first_name LIKE '%e%';
#9.顯示出表employees中first_name以'e'結尾的員工信息
SELECT *
FROM employees
WHERE first_name LIKE '%e';
#10.顯示出表employees部門編號在80-100之間的姓名、職位
SELECT first_name
FROM employees
WHERE department_id BETWEEN 80 AND 100;
#11.顯示出表employees的manager_id 是100,101,110的員工姓名和職位
SELECT first_name,manager_id
FROM employees
WHERE manager_id IN ('100','101','110');
三、排序查詢(order by)
select name from user where id>0 order by id desc;
執行順序(排序是放在select後的,因此可以用別名)
- from user
- where id>0
- select name
- order by id desc
#1.查詢員工的姓名和部門號和年薪,按年薪降序 按姓名升序
SELECT first_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM employees
ORDER BY 年薪 DESC,first_name ASC;
#2.選擇工資不在8000到17000的員工的姓名和工資,按工資降序
SELECT first_name,salary
FROM employees
WHERE salary NOT BETWEEN 8000 AND 17000
ORDER BY salary DESC;
#3.查詢郵箱中包含e的員工信息,並先按郵箱的字節數降序,再按部門號升序
SELECT *
FROM employees
WHERE email LIKE '%e%'
ORDER BY LENGTH(email) DESC,department_id ASC;
四、常見函數
常見函數
- 字符函數
- 數學函數
- 日期函數
- 流程控制函數
1.字符函數
#1.length 獲取參數值的字節個數(1個字=3個字節)
SELECT LENGTH('a老王');
#2.concat 拼接字符串
SELECT CONCAT('hellow,',first_name)
FROM employees;
#3.upper、lower
#示例:將姓變大寫,名變小寫,然後拼接
SELECT CONCAT(UPPER(first_name),LOWER(last_name))AS 大小寫拼接
FROM employees;
#4.substr、substring
注意:索引從1開始,截取多少個
#截取從指定索引處後面所有字符
SELECT SUBSTR('愛上是否',3);
#截取從指定索引處指定字符長度的
SELECT SUBSTRING('案說法計劃氨基酸客戶發jk',1,5);
#案例:姓名中首字符大寫,其他字符小寫然後用_拼接,顯示出來
SELECT CONCAT(UPPER(SUBSTR(first_name,1,1)),'_',LOWER(SUBSTR(first_name,2))) AS output FROM employees;
#5.instr 返回子串第一次出現的索引,如果找不到返回0
SELECT INSTR('阿薩ask房管局','薩');
#6.trim(去掉頭尾空格)
SELECT TRIM(' asf jaskf j ');
#7.lpad,rpad 用指定的字符實現左填充指定長度()
SELECT LPAD('奧是否快啦',10,'a');
#8.replace 替換
SELECT REPLACE('老王','老','小');
2.數學函數
#1.round 四捨五入
SELECT ROUND(54.6);
#2.ceil 向上取整,返回>=該參數的最小整數
SELECT CEIL(-1.02);
#3.floor 向下取整,返回<=該參數的最大整數
SELECT FLOOR(-9.99);
#4.truncate 截斷(數字,從小數點第幾位開始截斷)
SELECT TRUNCATE(1.69999,1);
#5.mod取餘
SELECT MOD(10,-3);
3.日期函數
#now 返回當前系統日期+時間
SELECT NOW();
#curdate 返回當前系統日期,不包含時間
SELECT CURDATE();
#curtime 返回當前時間,不包含日期
SELECT CURTIME();
#可以獲取指定的部分,年、月、日、小時、分鐘、秒
SELECT YEAR(NOW()) 年;
SELECT YEAR('1998-1-1') 年;
#str_to_date 將字符通過指定的格式轉換成日期
SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;
SELECT STR_TO_DATE('2012-09-23 05:54:45','%Y-%m-%d') AS 日期格式化;
#查詢入職日期爲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;
4.流程控制
#1.if(表達式,成立,不成立)
SELECT IF(salary>5000,'超過5k','沒有噢') FROM employees;
#2.case 表達式
where 匹配的值 then 輸出結果
案例:查詢員工的工資,要求部門號=30,顯示的工資爲1.1倍,部門號=40,顯示的工資爲1.2倍,其他部門,顯示的工資爲原工資
SELECT salary AS 原始工資,CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
ELSE salary
END AS 加部門獎金後工資
FROM employees;
5.分組函數
count()
avg()
sum()
max()
min()
#簡單使用
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;
/**
重點提一下count()
count(*)和count(1)和count(字段名)
count(*)和count(1)效果一樣,只不過count(1)在查詢的時候先建一個列都爲1再統計個數
而count(字段名)則是該列有不空的才統計+1
**/
五、分組查詢(需求中包含有每個,各個)
/*
語法:
1.select 查詢列表
2.from 表
3.【where 篩選條件】
4.group by 分組的字段
5.【order by 排序的字段】;
執行順序爲:from->where->group by->select>order by (排序是最後)
特點:
1、和分組函數一同查詢的字段必須是group by後出現的字段
2、篩選分爲兩類:分組前篩選和分組後篩選(一般來講,能用分組前篩選的,儘量使用分組前篩選,提高效率)
針對的表 位置 連接的關鍵字
分組前篩選 原始表 group by前 where
分組後篩選 group by後的結果集 group by後 having
3、分組可以按單個字段也可以按多個字段
4、可以搭配着排序使用
*/
#1.簡單的分組
#案例1:查詢每個工種的員工平均工資
SELECT AVG(salary) 平均工資,job_id
FROM employees
GROUP BY job_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 NULL
GROUP BY manager_id;
#3、分組後篩選
#案例1:查詢哪個部門的員工個數>5
SELECT department_id,COUNT(*)
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 最高工資>12000;
#案例3:領導編號>102的每個領導手下的最低工資大於5000的領導編號和最低工資
SELECT manager_id,MIN(salary) 最低工資
FROM employees
WHERE manager_id>120
GROUP BY manager_id
HAVING 最低工資>5000;
#4.添加排序
#案例:每個工種有獎金的員工的最高工資>6000的工種編號和最高工資,按最高工資升序
SELECT job_id,MAX(salary) 最高工資
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING 最高工資>6000
ORDER BY 最高工資 ASC;
六、連接查詢
1.內連接(sql92語法)
(1)等值連接
/*
① 多表等值連接的結果爲多表的交集部分
②n表連接,至少需要n-1個連接條件
③ 多表的順序沒有要求
④一般需要爲表起別名
⑤可以搭配前面介紹的所有子句使用,比如排序、分組、篩選
*/
#案例1:查詢員工名和對應的部門名
SELECT last_name,department_name
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`;
#2、爲表起別名
/*
①提高語句的簡潔度
②區分多個重名的字段
注意:如果爲表起了別名,則查詢的字段就不能使用原來的表名去限定
*/
#查詢員工名、工種號、工種名
SELECT e.`first_name`,e.`job_id`,j.`job_title`
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`;
#4、可以加篩選
#案例:查詢有獎金的員工名、部門名
SELECT e.`first_name`,d.`department_name`
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`commission_pct` IS NOT NULL;
#案例2:查詢城市名中第二個字符爲o的部門名和城市名
SELECT d.`department_name`,l.`city`
FROM locations l,departments d
WHERE d.`location_id`=l.`location_id`
AND l.`city` LIKE '_o%';
#5、可以加分組
#案例1:查詢每個城市的部門個數
SELECT COUNT(1),l.`location_id`
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY l.`location_id`;
#案例2:查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資
SELECT d.`department_name`,d.`manager_id`,MIN(e.`salary`)
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`salary` IS NOT NULL
GROUP BY d.`department_id`;
#6、可以加排序
#案例:查詢每個工種的工種名和員工的個數,並且按員工個數降序
SELECT j.`job_title`,COUNT(1)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY j.`job_id`
ORDER BY COUNT(1);
#7、可以實現三表連接?
#案例:查詢員工名、部門名和所在的城市
SELECT e.`first_name`,d.`department_name`,l.`city`
FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`;
(2)非等值連接
#案例1:查詢員工的工資和工資級別
SELECT e.`first_name`,j.`grade_level`
FROM employees e,job_grades j
WHERE e.`salary` BETWEEN j.`lowest_sal`AND j.`highest_sal`;
(3)自連接(一般用於分級查詢商品一級分類,二級分類,連接自身表)
#案例:查詢 員工名和上級的名稱
SELECT e.`first_name` 員工名稱,e2.`first_name` 領導名稱
FROM employees e,employees e2
WHERE e.`manager_id`=e2.`employee_id`;
2.內連接(sql99語法)
/**
相比92語法多了:[連接類型] join 表1 on 條件
語法:
SELECT
FROM 表1
INNER JOIN 表2 on 條件;
**/
#查詢員工名、工種號、工種名
SELECT e.`first_name`,j.`job_id`,j.`job_title`
FROM employees e
INNER JOIN jobs j ON e.`job_id`=j.`job_id`
3.外連接
外連接:查詢結果爲主表中所有的記錄。如果從表有匹配項,則顯示匹配項,如果從表中沒有匹配項,則顯示爲Null
應用場景:一般用於查詢主要中有但是從表中沒有的記錄
(1)左外連接
#1.顯示所有員工的姓名,部門號和部門名稱。
SELECT e.`first_name`,d.`department_id`,d.`department_name`
FROM employees e
LEFT JOIN departments d ON e.`department_id`=d.`department_id`;
#2.查詢90號部門員工的job_id和90號部門的location_id
#結果:部門id 員工job_id job_id location_id
SELECT d.`department_id`,e.`job_id`,d.`location_id`
FROM departments d
LEFT JOIN employees e ON d.`department_id`=e.`department_id`
WHERE d.`department_id`=90;
#3.選擇所有有獎金的員工的 last_name , department_name , location_id , city
SELECT e.`last_name`,d.`department_name`,l.`location_id`,l.`city`
FROM employees e
LEFT JOIN departments d ON e.`department_id`=d.`department_id`
LEFT JOIN locations l ON d.`location_id`= l.`location_id`
WHERE e.`commission_pct` IS NOT NULL;
#4.選擇city在Toronto工作的員工的 last_name , job_id , department_id , department_name
SELECT e.`last_name`,e.`job_id`,d.`department_id`,d.`department_name`
FROM employees e
LEFT JOIN departments d ON e.`department_id`=d.`department_id`
LEFT JOIN locations l ON d.`location_id`= l.`location_id`
WHERE l.`city`='Toronto';
#5.查詢每個工種、每個部門的部門名、工種名和最低工資
SELECT d.`department_name`,j.`job_title`,MIN(e.`salary`)
FROM employees e
LEFT JOIN departments d ON e.`department_id`=d.`department_id`
LEFT JOIN jobs j ON e.`job_id`=j.`job_id`
GROUP BY e.`job_id`,e.`department_id`
(2)右外連接
使用right join關鍵字,和左外類似。
(3)全外連接(mysql不支持)
兩張表互連,匹配的顯示信息,不匹配的顯示爲Null
4.總結連表查詢
七、子查詢(最難***)
/*
含義:
出現在其他語句中的select語句,稱爲子查詢或內查詢
外部的查詢語句,稱爲主查詢或外查詢
分類:
按子查詢出現的位置:
select後面:
僅僅支持標量子查詢
from後面:
支持表子查詢
where或having後面:★
標量子查詢(單行) √
列子查詢 (多行) √
行子查詢
exists後面(相關子查詢)
表子查詢
按結果集的行列數不同:
標量子查詢(結果集只有一行一列)
列子查詢(結果集只有一列多行)
行子查詢(結果集有一行多列)
表子查詢(結果集一般爲多行多列)
*/
1.跟在where/having後
特點:
①子查詢放在小括號內
②子查詢一般放在條件的右側
③標量子查詢,一般搭配着單行操作符使用
> < >= <= = <>
列子查詢,一般搭配着多行操作符使用
in、any/some、all
④子查詢的執行優先於主查詢執行,主查詢的條件用到了子查詢的結果
*/
#1.標量子查詢★
#案例1:誰的工資比 Abel 高?
#①查詢Abel的工資
#②查詢員工的信息,滿足 salary>①結果
SELECT last_name
FROM employees
WHERE salary>(
SELECT salary
FROM employees
WHERE last_name='Abel');
#案例2:返回job_id與141號員工相同,salary比143號員工多的員工 姓名,job_id 和工資
#①查詢141號員工的job_id
#③查詢員工的姓名,job_id 和工資,要求job_id=①並且salary>②
SELECT first_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,job_id,salary
FROM employees
WHERE salary=(
SELECT MIN(salary)
FROM employees);
#案例4:查詢最低工資大於50號部門最低工資的部門id和其最低工資
#①查詢50號部門的最低工資
#②查詢每個部門的最低工資
#③ 在②基礎上篩選,滿足min(salary)>①
#③ 在②基礎上篩選,滿足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);
#2.列子查詢(多行子查詢)★
#案例1:返回location_id是1400或1700的部門中的所有員工姓名
#①查詢location_id是1400或1700的部門編號
#②查詢員工姓名,要求部門號是①列表中的某一個
SELECT first_name
FROM employees
WHERE department_id IN(
SELECT DISTINCT d.`department_id`
FROM departments d
WHERE d.`location_id` IN(1400,1700));
2.跟在select後
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
) 部門名;
3.跟在from後面
/*
將子查詢結果充當一張表,要求必須起別名
*/
#案例:查詢每個部門的平均工資的工資等級
#①查詢每個部門的平均工資
#②連接①的結果集和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;
4.跟在exists後面
#案例1:查詢有員工的部門名
SELECT department_name
FROM departments d
WHERE EXISTS(
SELECT *
FROM employees e
WHERE d.`department_id`=e.`department_id`
);
八、分頁查詢
/*
應用場景:當要顯示的數據,一頁顯示不全,需要分頁提交sql請求
語法:
select 查詢列表
from 表
【join type join 表2
on 連接條件
where 篩選條件
group by 分組字段
having 分組後的篩選
order by 排序的字段】
limit 【offset,】size;
!!執行順序:from->join->on->where->group by->having->select->order by->limit
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;
九、union聯合查詢
#進階9:聯合查詢
/*
union 聯合 合併:將多條查詢語句的結果合併成一個結果
語法:
查詢語句1
union
查詢語句2
union
...
應用場景:
要查詢的結果來自於多個表,且多個表沒有直接的連接關係,但查詢的信息一致時
特點:★
1、要求多條查詢語句的查詢列數是一致的!
2、要求多條查詢語句的查詢的每一列的類型和順序最好一致
3、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;
#案例:查詢中國用戶中男性的信息以及外國用戶中年男性的用戶信息
SELECT id,cname FROM t_ca WHERE csex='男'
UNION ALL
SELECT t_id,tname FROM t_ua WHERE tGender='male';