sql 最核心的查詢語句!!!!
增刪改
單表查詢
select語句的完整寫法
關鍵字的書寫順序
執行順序
多表查詢
笛卡爾積
內連接
左外連接
右外連接
全外連接
通過合並左外連接和右外連接
子查詢
一個查詢包含另一個查詢 被包含的叫子查詢
當一個查詢的結果 是另一個查詢的條件時 這個查詢叫子查詢
子查詢需要用括號包起來
====================================
1.數據增刪改
增加
insert [into] 表名[(可選字段名)] values(一堆值1),(一堆值2),.....
into 可以省略
表名后的字段可以選
如果寫了 后面的values中的值必須與表名后的字段一一對應
如果沒寫 后面的values中的值必須與表的所有字段一一對應
values后面可以給多組值 用逗號隔開
刪除
delete from 表名[where 條件]
條件不寫 是刪除所有記錄 是一行一行刪除 注意自增id 不會歸零
truncate 重建表 先記錄表結構 刪除整個表再重新建出來表 自增id 會歸零
更新數據
update 表名 set 字段名 = 值[,字段2 = 值2],[where 條件]
可以一次性修改多個字段的值用逗號隔開
條件如果不寫 修改所有記錄
2.單表查詢
不帶關鍵字的查詢
select {1.*|2.字段名|3.四則運行|4.聚合函數} from 表名 [where 條件]
1.* 表示查詢所有字段
2.可以手動要查詢的字段
3.字段的值可以進行加減乘除運算
4.聚合函數,用於統計
where 是可選的
select 的完整語法
數據准備
create table stu(id int primary key auto_increment,name
char(10),math float,english float);
insert into stu values(null,"趙雲",90,30);
insert into stu values(null,"小喬",90,60);
insert into stu values(null,"小喬",90,60);
insert into stu values(null,"大喬",10,70);
insert into stu values(null,"李清照",100,100);
insert into stu values(null,"鐵拐李",20,55);
insert into stu values(null,"小李子",20,55);
3 關鍵字的作用
distinct 去除重復數據 所有數據全都重復才算重復
where 在逐行讀取數據時的一個判斷條件
group by 對數據分組
having 對分組后的數據進行過濾
order by 對結果排序
limit 指定獲取數據條數
完整的select 語句 語法,書寫順序是固定的 *****
select [distinct] * from 表名
[where
group by
having
order by
limit
]
注意 在書寫時 必須按照這個順序來寫 !!! 但是順寫順寫不代表執行順序
關鍵字的執行順序 *****
from
where
group by
having
select
distinct
order by
limit
1.找到表:from
2.拿着where指定的約束條件,去文件/表中取出一條條記錄
3.將取出的一條條記錄進行分組group by,如果沒有group by,則整體作為一組
4.將分組的結果進行having過濾
5.執行select
6.去重
7.將結果按條件排序:order by
8.限制結果的顯示條數
簡單查詢
定義顯示格式:
concat()函數用於拼接字符串
# 補充concat(不分組時用)
select name as 姓名,salary as 薪資 from emp;
select concat("NAME: ",name) as 姓名,concat("SAL: ",salary) as 薪資 from emp;
通過四則運算查詢
SELECT name, salary*12 FROM employee;
SELECT name, salary*12 AS Annual_salary FROM employee;
SELECT name, salary*12 Annual_salary FROM employee;
select
(case
when english + math > 120 then
concat(name," nice")
when english + math <= 130 then
concat(name," shit")
end
) ,english,math from stu;
A, distinct去重
當所有字段的值都相同才會去重
select distinct post,avg(salary) from emp
where age >= 30
group by post
having avg(salary) > 10000;
B, where 條件
where字句中可以使用:
1. 比較運算符:> < >= <= <> !=
2. between 80 and 100 值在10到20之間
3. in(80,90,100) 值是10或20或30
4. like 'egon%'
pattern可以是%或_,
%表示任意多字符
_表示一個字符
5. 邏輯運算符:在多個條件直接可以使用邏輯運算符 and or not
create table emp (id int,name char(10),sex char,dept char(10),job
char(10),salary double);
insert into emp values
(1,"劉備","男","市場","總監",5800),
(2,"張飛","男","市場","員工",3000),
(3,"關羽","男","市場","員工",4000),
(4,"孫權","男","行政","總監",6000),
(5,"周瑜","男","行政","員工",5000),
(6,"小喬","女","行政","員工",4000),
(7,"曹操","男","財務","總監",10000),
(8,"司馬懿","男","財務","員工",6000);
where后可用:
四則運算+-*/
><=!
between and
in
not null
and or not
like
regexp
any/all where 10>any(select age from emp)
where 10>all(select age from emp)
select id,name from db39.emp where id >= 3 and id <= 6
select * from db39.emp where id between 3 and 6;
select * from emp where salary = 20000 or salary = 18000 or salary = 17000;
select * from emp where salary in (20000,18000,17000);
要求:查詢員工姓名中包含i字母的員工姓名與其薪資
select name,salary from db39.emp where name like '%i%'
要求:查詢員工姓名是由四個字符組成的的員工姓名與其薪資
select name,salary from db39.emp where name like '____';
select name,salary from db39.emp where char_length(name) = 4;
select * from db39.emp where id not between 3 and 6;
select * from emp where salary not in (20000,18000,17000);
要求:查詢崗位描述為空的員工名與崗位名
select name,post from db39.emp where post_comment is NULL;
select name,post from db39.emp where post_comment is not NULL;
C, group by 分組查詢 *****
#1、首先明確一點:分組發生在where之后,即分組是基於where之后得到的記錄而進行的
#2、分組指的是:將所有記錄按照某個相同字段進行歸類,比如針對員工信息表的職位分組,或者按照性別進行分組等
#3、為何要分組呢?
取每個部門的最高工資
取每個部門的員工數
取男人數和女人數
小竅門:‘每’這個字后面的字段,就是我們分組的依據
#4、大前提:
可以按照任意字段分組,但是分組完畢后,比如group by post,
只能查看post字段,如果想查看組內信息,需要借助於聚合函數
什么是分組
把一個整體 分割為多個部分
為什么分組
在數據庫中分組為了統計 *****
分組后 組里的詳細記錄就被隱藏起來了 不能直接查看
dept 一分組 變成三條記錄 每個組中卻包含多條記錄 沒辦法顯示
一定要顯示的話
可以使用group_concat(字段名)
可以將多個值拼接成一個字符串
注意*****: 1.只有查看出現在group by 后面的字段, 其他都被影藏了
2.聚合函數不能寫在where的后面 where最先執行 它的作用硬盤讀取數據並
過濾 以為數據還沒有讀取完 此時不能進行統計
聚合函數:count
max /min
avg
sum
了解:
在mysql 5.6中 分組后會默認顯示 每組的第一條記錄 這是沒有意義的
5.7不顯示 因為5.7中 sql_mode中自帶 ONLY_FULL_GROUP_BY
group by 后面可以有多個分組與依據 會按照順序執行
#設置sql_mode為only_full_group_by,意味着以后但凡分組,只能取到分組的依據
mysql> set global sql_mode="strict_trans_tables,only_full_group_by";
#每個部門的最高工資
select post,max(salary) from emp group by post;
select post,min(salary) from emp group by post;
select post,avg(salary) from emp group by post;
select post,sum(salary) from emp group by post;
select post,count(id) from emp group by post;
#group_concat(分組之后用)
select post,group_concat(name) from emp group by post;
select post,group_concat(name,"_SB") from emp group by post;
select post,group_concat(name,": ",salary) from emp group by post;
select post,group_concat(salary) from emp group by post;
# 補充as語法
mysql> select emp.id,emp.name from emp as t1; # 報錯
mysql> select t1.id,t1.name from emp as t1;
# 查詢四則運算
select name,salary*12 as annual_salary from emp;
分組練習
1. 查詢崗位名以及崗位包含的所有員工名字
select post,group_concat(name) from emp group by post;
2. 查詢崗位名以及各崗位內包含的員工個數
select post,count(id) from emp group by post;
3. 查詢公司內男員工和女員工的個數
select sex,count(id) from emp group by sex;
4. 查詢崗位名以及各崗位的平均薪資
select post,avg(salary) from emp group by post;
5. 查詢崗位名以及各崗位的最高薪資
6. 查詢崗位名以及各崗位的最低薪資
7. 查詢男員工與男員工的平均薪資,女員工與女員工的平均薪資
select sex,avg(salary) from emp group by sex;
8、統計各部門年齡在30歲以上的員工平均工資
select post,avg(salary) from emp where age >= 30 group by post;
聚合函數
#強調:聚合函數聚合的是組的內容,若是沒有分組,則默認一組
示例:
SELECT COUNT(*) FROM employee;
SELECT COUNT(*) FROM employee WHERE depart_id=1;
SELECT MAX(salary) FROM employee;
SELECT MIN(salary) FROM employee;
SELECT AVG(salary) FROM employee;
SELECT SUM(salary) FROM employee;
SELECT SUM(salary) FROM employee WHERE depart_id=3;
D, having過濾
HAVING與WHERE不一樣的地方在於!!!!!!
#!!!執行優先級從高到低:where > group by > having
#1. Where 發生在分組group by之前,因而Where中可以有任意字段,但是絕對不能使用聚合函數。
#2. Having發生在分組group by之后,因而Having中可以使用分組的字段,無法直接取到其他字段,可以使用聚合函數
having的語法格式與where一模一樣,只不過having是在分組之后進行的進一步過濾
即where不能用聚合函數,因為數據還沒有全部讀取,無法統計.而having是可以用聚合函數,這也是他們倆最大的區別
1、統計各部門年齡在30歲以上的員工平均工資,並且保留平均工資大於10000的部門
select post,avg(salary) from emp
where age >= 30
group by post
having avg(salary) > 10000;
#強調:having必須在group by后面使用
select * from emp
having avg(salary) > 10000;
E, order by 排序用的
按單列排序
SELECT * FROM employee ORDER BY salary;
SELECT * FROM employee ORDER BY salary ASC;
SELECT * FROM employee ORDER BY salary DESC;
按多列排序:先按照age排序,如果年紀相同,則按照薪資排序
SELECT * from employee
ORDER BY age,
salary DESC;
asc 表示升序 是默認的
desc 表示降序
by 后面可以有多個排序依據
select * from emp order by salary asc; #默認升序排
select * from emp order by salary desc; #降序排
select * from emp order by age desc; #降序排
select * from emp order by age desc,salary asc; #先按照age降序排,再按照薪資升序排
# 統計各部門年齡在10歲以上的員工平均工資,並且保留平均工資大於1000的部門,
然后對平均工資進行排序
select post,avg(salary) from emp
where age > 10
group by post
having avg(salary) > 1000
order by avg(salary)
;
F, limit 限制顯示條數
limit a,b
limit 1,5
從1開始 到5結束 錯誤
從1開始 不包含1 取5條 正確
select * from emp limit 3;
select * from emp order by salary desc limit 1;
分頁查詢
每頁顯示3條 共有10條數據
if 10 % 3 == 0:
10 / 3
else:
10/3 +1
總頁數4
第一頁
select *from emp limit(0,3)
第二頁
select *from emp limit(3,3)
正表達式匹配
由於like只能使用% 和 _ 不太靈活
可以將like換為 regexp 來使用正則表達式
select * from emp where name regexp '^jin.*(n|g)$';
4.多表查詢 ******
數據准備
create table emp (id int,name
char(10),sex char,dept_id int);
insert emp values(1,"大黃","m",1);
insert emp values(2,"老王","m",2);
insert emp values(3,"老李","w",30);
create table dept (id int,name char(10));
insert dept values(1,"市場");
insert dept values(2,"財務");
insert dept values(3,"行政");
1.笛卡爾積查詢
select *from 表1,表n
查詢結果是
左表中的每條記錄 與右表中的每條記錄都關聯一遍
因為 他不知道什么樣的對應關系是正確 只能幫你都對一遍
會產生一堆垃圾數據,需要進行過濾 where 從表的外鍵 =主表的主鍵
a表有m條記錄 b表有n條記錄
笛卡爾積結果為m * n 記錄
需要自己篩選出正確的關聯關系
select *from emp,dept where emp.dept_id = dept.id;
2.內連接查詢inner join
把兩張表有對應關系的記錄連接成一張虛擬表 (就是笛卡爾積查詢)
內指的是能夠匹配上的數據
select * from emp [inner] join dep on emp.dep_id = dep.id;
#應用:
select * from emp,dep where emp.dep_id = dep.id and dep.name = "技術"; # 不要用where做連表的活
select * from emp inner join dep on emp.dep_id = dep.id
where dep.name = "技術";
3.左外鏈接查詢left join
在內連接的基礎上,保留左邊沒有對應關系的記錄
左表數據全部顯示 右表只顯示匹配上的
select *from emp left join dept on emp.dept_id = dept.id;
4.右外鏈接查詢right join
在內連接的基礎上,保留右邊沒有對應關系的記錄
右表數據全部顯示 左表只顯示匹配上的
select *from emp right join dept on emp.dept_id = dept.id;
內和外的理解 內指的是匹配上的數據 外指的是沒匹配上的數據
5.全外連接
在內連接的基礎上,保留左、右邊沒有對應關系的記錄
左右兩邊的記錄完全顯示
select *from emp full join dept on emp.dept_id = dept.id; ##mysql不支持
union 合並查詢,去除重復數據 只能合並字段數量相同的表
select *from emp left join dept on emp.dept_id = dept.id
union
select *from emp right join dept on emp.dept_id = dept.id;
union all 不會去除重復數據
#補充:多表連接可以不斷地與虛擬表連接
查找各部門最高工資
select t1.* from emp as t1
inner join
(select post,max(salary) as ms from emp group by post) as t2
on t1.post = t2.post
where t1.salary = t2.ms
;
三表查詢
create table stu(id int primary key auto_increment,name char(10));
create table tea(id int primary key auto_increment,name char(10));
create table tsr(id int primary key auto_increment,t_id int,s_id int,
foreign key(s_id) references stu(id),
foreign key(s_id) references stu(id));
insert into stu values(null,"張三"),(null,"李李四");
insert into tea values(null,"egon"),(null,"wer");
insert into tsr values(null,1,1),(null,1,2),(null,2,2);
select *from stu join tea join tsr
on stu.id = tsr.s_id and tea.id = tsr.t_id
where tea.name = "egon";
多表查詢套路
1.把所有表都連起來
2.加上連接條件
3.如果有別的過濾條件 加上where
5.子查詢
子查詢是將一個查詢語句嵌套在另一個查詢語句中。(內層查詢)
#2:內層查詢語句的查詢結果,可以為外層查詢語句提供查詢條件。
#3:子查詢中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字
#4:還可以包含比較運算符:= 、 !=、> 、<等
什么時候使用子查詢
當一次查詢無法得到想要結果時 需要多次查詢
子查詢原理,解決問題的思路
是把一個復雜的問題 拆分為多個簡單的問題
是把一個復雜的查詢 拆分為多個簡單的查詢
給你部門的的名稱
查部門有哪些人?
第一步查到部門的id
第二部 拿着id去員工表查詢
select *from dept join emp on dept.id = emp.dept_id;
select *from emp join
# 使用子查詢 得到 每個部門的id 以及部門的 最高工資 形成一個虛擬表 把原始表和 虛擬表連接在一起
(select dept_id,max(salary)as m from emp group by dept_id) as t1
# 如果這個人的部門編號 等於 虛擬表中的部門編號
on emp.dept_id = t1.dept_id
and
# 並且 如果這個人的工資 等於 虛擬表中的最高工資 就是你要找的人
emp.salary = t1.m;
create table emp (id int,name char(10),sex char,age int,dept_id int,job
char(10),salary double);
insert into emp values
(1,"劉備","男",26,1,"總監",5800),
(2,"張⻜飛","男",24,1,"員⼯工",3000),
(3,"關⽻羽","男",30,1,"員⼯工",4000),
(4,"孫權","男",25,2,"總監",6000),
(5,"周瑜","男",22,2,"員⼯工",5000),
(6,"⼩小喬","女",31,2,"員⼯工",4000),
(7,"曹操","男",19,3,"總監",10000),
(8,"司⻢馬懿","男",24,3,"員⼯工",6000);
select emp.name from emp inner join dep on emp.dep_id = dep.id where dep.name="技術";
select name from emp where dep_id =
(select id from dep where name="技術");
1 帶IN關鍵字的子查詢
大多數子查詢都可以被連接查詢代替
in (1,2)
#查詢平均年齡在25歲以上的部門名
select name from dep where id in
(select dep_id from emp group by dep_id having avg(age) > 25);
2 帶比較運算符的子查詢
select dep.name from emp inner join dep on emp.dep_id = dep.id
group by dep.name
having avg(age) > 25;
3 帶EXISTS關鍵字的子查詢
EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。
而是返回一個真假值。True或False
當返回True時,外層查詢語句將進行查詢;當返回值為False時,外層查詢語句不進行查詢
#查看不足2人的部門名(子查詢得到的是有人的部門id)
select * from emp where exists (
select id from dep where id > 3
);
#查詢每個部門最新入職的那位員工
select t1.id,t1.name,t1.post,t1.hire_date,t2.post,t2.max_date from emp as t1 inner join
(select post,max(hire_date) as max_date from emp group by post) as t2
on t1.post = t2.post
where t1.hire_date = t2.max_date
;