語句執行順序
創建emp表,字段有id, name, sex, age, hire_data, post, post_comment, salary
create table emp( id int not null unique auto_increment, name varchar(20) not null, sex enum('male','female') not null default 'male', #大部分是男的 age int(3) unsigned not null default 28, # unsigned:非符號 hire_date date not null, post varchar(50), post_comment varchar(100), salary double(15,2), # 15位數字,兩個小數 office int, #一個部門一個屋子 depart_id int );
往表中插入數據
#三個部門:教學,銷售,運營 insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values ('bob','male',18,'20170301','teacher',7300.33,401,1), #以下是教學部 ('mac','male',78,'20150302','teacher',1000000.31,401,1), ('kevin','male',81,'20130305','teacher',8300,401,1), ('stv','male',73,'20140701','teacher',3500,401,1), ('office','male',28,'20121101','teacher',2100,401,1), ('jerry','female',18,'20110211','teacher',9000,401,1), ('tiny','male',18,'19000301','teacher',30000,401,1), ('sean','male',48,'20101111','teacher',10000,401,1), ('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是銷售部門 ('丫丫','female',38,'20101101','sale',2000.35,402,2), ('丁丁','female',18,'20110312','sale',1000.37,402,2), ('星星','female',18,'20160513','sale',3000.29,402,2), ('格格','female',28,'20170127','sale',4000.33,402,2), ('張野','male',28,'20160311','operation',10000.13,403,3), #以下是運營部門 ('程咬金','male',18,'19970312','operation',20000,403,3), ('程咬銀','female',18,'20130311','operation',19000,403,3), ('程咬銅','male',18,'20150411','operation',18000,403,3), ('程咬鐵','female',18,'20140512','operation',17000,403,3) ;
一 where約束條件
執行順序
from
where
select
1.查詢id大於等於3小於等於6的數據

select * from emp where id >= 3 and id <= 6 #第一種寫法 select * from emp where id between 3 and 6 #第二種寫法
2.查詢薪資是20000或者18000或者17000的數據

select * from emp where salaary=20000 or salary=18000 or salary=17000 #第一種寫法 select * from emp where salary in (20000,18000,17000) #第二種寫法
3.查詢員工姓名中包含o字母的員工姓名及薪資

select name, salary from emp where name like '%o%'; # like:模糊匹配,有兩個語法. %:匹配多個任意字符 _:匹配一個任意字符
4.查詢員工姓名是由四個字符組成的員工姓名與其薪資

select name, salary from emp where name like '____'; # 第一種寫法 select name, salary from emp where char_length(name) = 4 #第二種寫法
5.查詢崗位描述為空的員工名與崗位名 注意:mysql中的空字段是用null表示的, 在查詢null字段時, 不能使用=號,只能使用is, mysql對大小寫不敏感

select name, post from emp where post_comment is null
二 group by
在我們所插入的數據中,數據分組的應用場景:每個部門的平均薪資,男女比例等
如何按照部門分組呢?
select * from emp group by post;
再次使用select id,name from emp group by post; 去查的時候會報錯, 如果不報錯,說明沒有設置嚴格模式
設置sql_mode為only_full_group_by,意味着以后但凡分組,只能取到分組的依據,不應該在去取組里面的單個元素的值,那樣的話分組就沒有意義了,因為不分組就是對單個元素信息的隨意獲取
set global sql_mode="strict_trans_tables,only_full_group_by";
強調:只要分組了,就不能夠再“直接”查找到單個數據信息了,只能獲取到組名
首先我們要想一個問題, 既然分組之后我們不能夠'直接'查找單個的數據信息了,那么我們如何去查看每個部門的最高薪資呢? 這個時候我們可以借助聚合函數去查.
聚合函數:
max:最大值
min:最小值
avg:平均值
sum:求和
count:計數
1.查看每個部門的最高薪資

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; # 這里我們可以使用任意非空字段去查,因為count是計數的操作,統計字段中數據出現了多少次,推薦使用id去查
group_concat(分組后使用):可以查看組內所有的數據,也可以進行拼接字符串操作
comcat(不分組時使用)
2. 查詢分組之后的部門名稱和每個部門下所有的學生姓名

select post, group_concat(name) from emp group by post;
在分組內的每個名字之前加上q字符

select post,group_concat('q', name) from emp group by post;
不分組時用

select concat('NAME:',name) as 姓名, concat('SALARY:',salary) as 薪資 from emp; #as 起別名
練習:
1. 查詢崗位名以及崗位包含的所有員工名字
2. 查詢崗位名以及各崗位內包含的員工個數
3. 查詢公司內男員工和女員工的個數
4. 查詢崗位名以及各崗位的平均薪資
5. 查詢崗位名以及各崗位的最高薪資
6. 查詢崗位名以及各崗位的最低薪資
7. 查詢男員工與男員工的平均薪資,女員工與女員工的平均薪資
答案參考

select post,group_concat(name) from emp group by post; select post,count(id) from emp group by post; select sex,count(id) from employee group by sex; select post,avg(salary) from emp group by post; select post,max(salary) from employee group by post; select post,min(salary) from employee group by post; select sex,avg(salary) from employee group by sex;
8.統計個部門年齡在30以上的員工平均工資
這里涉及到一個執行順序
from
where
group by
select

select post,avg(salary) from emp where age>30 group by post;
三 having
跟where是一模一樣的,也是用來篩選數據,但是having是跟在group by之后的,where是對整體數據做一個初步的篩選,而having是對分組之后的數據再進行一次針對性的篩選
1.統計各部門年齡在30歲以上的員工平均工資,並且保留平均工資大於10000的部門
執行順序
from
where
group by
having
select

select post,avg(salary) from emp where age > 30 group by post having avg(salary)>10000;
四 distinct去重
去重必須數據是一模一樣的才能去重,只要有一個不一樣 都不能算是的重復的數據
select distinct id, age from emp; # 這樣寫達不到去重的效果,只有一模一樣的才能去重
select distinct age from emp; # 達到去重效果
五 order by
order by:排序, 默認是升序(asc),如果要調整成降序,要使用關鍵字desc
select * from emp order by salary; #對salary進行排序,默認升序
select * from emp order by salary desc; # 使用降序進行排序
統計各部門年齡在10歲以上的員工平均工資,並且保留平均工資大於1000的部門,然后對平均工資進行排序(降序)

select post,avg(salary) from emp where age > 10 group by post having avg(salary) > 1000 order by avg(salary) desc;
六 limit
limit:限制展示數據的條數
當limit只有一個參數的時候 表示的是只展示幾條
select * from emp limit 5;
當limit有兩個參數的時候 第一個參數表示的起始位置 第二個參數表示從起始位置開始往后展示的條數
select * from emp limit 5, 10;
查詢工資最高的人的詳細信息
思路:先根據薪資按照降序排序,第一條就是薪資最高的那個人,使用limit拿到1條數據
select * from emp order by salary desc limit 1;
七 正則
select * from emp where name regexp '^j.*(n|y)$'; 正則解釋: ^j,以j開頭 .*,匹配0到多個字符 (n|y)$,以n或者y結尾
多表查詢
創建兩張表
create table dep( id int, name varchar(20) ); create table emp( id int primary key auto_increment, name varchar(20), sex enum('male','female') not null default 'male', age int, dep_id int );
插入數據
insert into dep values (200,'技術'), (201,'人力資源'), (202,'銷售'), (203,'運營'); insert into emp(name,sex,age,dep_id) values ('json','male',18,200), ('exit','female',48,201), ('kevin','male',38,201), ('nick','female',28,202), ('bob','male',18,200), ('jerry','female',18,204) ;
如下圖所示:
如何查詢json屬於哪個部門呢? 我們先來推導一下
select * from emp,dep;
這樣查出來的數據明顯不是我們想要的,冗余的數據過多,把每一個部門都顯示了一遍
那我們只顯示相同的id結果會如何呢?
select * from emp,dep where emp.dep_id = dep.id
這種聯表查詢太麻煩了
多表查詢的方式
內連接(inner join): 只去兩張表有對應關系的記錄
select * from emp inner join dep on emp.dep_id = dep.id; # on后面跟的是查詢條件
左連接(left join): 在內連接的基礎上保留左表沒有對應關系的記錄
select * from emp left join dep on emp.dep_id = dep.id;
右連接(right join): 在內連接的基礎上保留右表沒有對應關系的記錄
select * from emp right join dep on emp.dep_id = emp.id;
全連接(union): 在內連接的基礎上保留左,右表沒有對應關系的記錄
select * from emp left join dep on emp.dep_id = dep.id union select * from emp right join dep on emp.dep_id = dep.id;
子查詢
就是將一個查詢語句的結果用括號括起來當作另外一個查詢語句的條件去用
查詢部門是技術或者人力資源的員工信息
select * from emp where dep_id in (select id from dep where name = "技術" or name = "人力資源"); # 括號內就是另一張表的查詢結果,當做了另一張表的查詢條件