數據庫——單表查詢、多表查詢的常用關鍵字


數據庫——單表查詢、多表查詢的常用關鍵字

一 單表查詢

1、前期表與數據准備

# 創建一張部門表
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,
  hire_date date not null,
  post varchar(50),
  post_comment varchar(100),
  salary double(15,2),
  office int, # 一個部門一個屋子
  depart_id int
);


# 插入記錄
# 三個部門:教學,銷售,運營
insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values
('tank','male',17,'20170301','張江第一帥形象代言部門',7300.33,401,1), # 以下是教學部
('egon','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('jason','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jerry','female',18,'20110211','teacher',9000,401,1),
('大餅','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);

# PS:如果在windows系統中,插入中文字符,select的結果為空白,可以將所有字符編碼統一設置成gbk

插入表數據

2、語法書寫與執行順序

# 在寫SQL命令是注意兩點:
		- 書寫順序
  			# 查詢id是4-5記錄的id與名字
  			- select id, name from emp where id > 3 and id < 6;
  			
# PS: 根據現實生活中圖書館管理員找書的過程: 先知道書在哪個位置,然后再判斷要找的是什么書,最后再找書本中的第幾頁;
  	
  	- 執行順序
    	- from  # 找圖書館
      	- where  # 書在圖書館中的位置
      	- select  # 查找書中的某一頁內容

# 注意: 執行順序必須要清楚!!!

# 查詢數據量大時,可以在表后面 + \G,修改顯示格式;
select * from emp\G  # 不要加分號

3、where約束條件

# PS: 根據執行順序來書寫 SQL語句,一步一步來寫;

# 1.查詢id大於等於3小於等於6的數據
select * from emp where id >= 3 and id <= 6;
# between: 兩者之間
# and: 與
select * from emp where id between 3 and 6;


# 2.查詢薪資是20000或者18000或者17000的數據
# or:  或者
select * from emp where salary=20000 or salary=18000 or salary=17000;
# in: 在什么里
select * from emp where salary in (20000, 18000, 17000);


# 3.查詢員工姓名中包含o字母 的 員工姓名和薪資
# like: 模糊匹配
# %: 匹配0個或多個任意字符
# _: 匹配一個任意字符
select name, salary from emp where name like "%o%";


# 4.查詢員工姓名是由四個字符組成的員工姓名與薪資
select name, salary from emp where name like "_____";
# char_length(字段): 獲取字段長度
select name, salary from emp where char_length(name) = 4;


# 5.查詢id小於3或者大於6的數據
select * from emp where id < 3 or id > 6;
select * from emp where id not between 3 and 6;


# 6.查詢薪資不在20000,18000,17000范圍的數據
select * from emp where salary not in (20000, 18000, 17000);


# 7.查詢崗位描述為空的員工名與崗位名  
# 注意: 針對null不能用等號,只能用is
select name, post from emp where post_comment = null;
select name, post from emp where post_comment is null;
select name,post from emp where post_comment is not null;

4、group by

# group by: 分組  
# 比如: 一張員工表中有性別字段,可以根據性別分組,一組是男性,一組是女性,或者是根據部門分組,有教學部、銷售部等...

# 1.按部門分組
# 嚴格模式下只能獲取分組字段post數據, 無法獲取其他字段信息,就好比是進程之間數據隔離,但是可以使用聚合函數來獲取
'''
聚合函數: max, min, sum, avg, count
'''
# 非嚴格模式下不報錯
select * from emp group by post;  # 報錯
select id, name from emp group by post;  # 報錯
select post from emp group by post;

# 嚴格模式設置
"""
設置sql_mode為only_full_group_by,意味着以后但凡分組,只能取到分組的依據,
不應該在去取組里面的單個元素的值,那樣的話分組就沒有意義了,因為不分組就是對單個元素信息的隨意獲取
"""
show variables like "%mode%";
set global sql_mode="strict_trans_tables,only_full_group_by";


# 2.獲取每個部門的最高工資 ----> 畫圖,講述數據分組后,發生了什么事情
select post, max(salary) from emp group by post;
# as: 起別名; 給獲取出來的數據字段名,設置別名
select post as '部門', max(salary) as '薪資' from emp group by post;
# 可簡寫, 但不推薦
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;

# 每個部門的人數: count() 中傳任意參數都沒問題
select post, count(id) from emp group by post;
select post, count(post) from emp group by post;


# 3.查詢分組之后的部門名稱和每個部門下所有員工的姓名
# group_concat(name): 不僅可以獲取分組后的某一個字段,並且可以對字符串進行拼接
select post, group_concat(name) from emp group by post;
# 給每個部門的員工名字前 + NB_
select post, group_concat('NB_', name) from emp group by post;
# 拼接部門員工名字+薪資
select post, group_concat(name, ":", salary) from emp group by post;


# 4.補充concat(不分組時用)拼接字符串達到更好的顯示效果 as語法使用
select concat('Name: ', name) as '名字', concat('Sal: ', salary) as '薪資' from emp;


# 5.補充as語法 即可以給字段起別名也可以給表起
select emp.name as '名字', emp.salary as '薪資' from emp;


# 6.查詢四則運算
# 求各部門所有員工的年薪
select name, salary * 12 as annual_salary from emp;

5、練習題

# 寫查詢語句的步驟:  先看需要查哪張表,然后看有沒有什么限制條件, 再看需要根據什么分組,最后再看需要查看什么字段!

執行順序:
		from --> where --> group by --> select 
# 注意: 聚合函數: 
	1、只能在group by后(執行順序)使用  
	2、若查詢語句沒有group by,則默認整張表就是一個分組。
	
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. 查詢崗位名以及各崗位的最高薪資
select post, max(salary) from emp group by post;

6. 查詢崗位名以及各崗位的最低薪資
select post, min(salary) from emp group by post;

7. 查詢男員工與男員工的平均薪資,女員工與女員工的平均薪資
select sex, avg(salary) from emp group by sex;

8、統計各部門年齡在30歲以上的員工平均工資
select post, avg(salary) from emp where age > 30 group by post;
# 分結構查詢: 先查找所有年齡30歲以上的員工,再根據部門分組查詢它們的平均工資;
select * from emp where age > 30;
select post, avg(salary) from emp where age > 30 group by post;

6、having

# 目前掌握的查詢基礎
- 書寫順序:
    select 字段1, 字段2...
    from 表名
    where 查詢條件
    group by 分組條件

- 執行順序:
		from
		where 
		group by
		select

# having: 過濾
    1.having與where語法一樣,只不過having需要在group by后使用;
    2.where 不能使用聚合函數,但having可以;

1、統計各部門年齡在30歲以上的員工平均工資,並且保留平均工資大於10000的部門;
select post, avg(salary) from emp where age > 30 group by post having avg(salary) > 10000;

-執行順序:
		- from
		- where 
		- group by 
		- having
		- select

7、distinct

# distinct: 去重
# 注意: 查詢的字段值必須是重復的才有效,只要有一個字段值是不重復的就沒有效果。
select distinct id, post from emp;
select distinct post from emp;
select distinct age from emp;

執行順序:
		- from
		- where 
		- group by 
		- having
		- select 
		- distinct

8、order by

# order by: 排序, 獲取select獲取的數據進行排序

# 1、根據薪資進行升序
select * from emp order by salary;  # 默認升序
select * from emp order by salary asc;  # 指定升序
select * from emp order by salary desc;  # 指定降序

# 2、根據年齡進行降序排列
select * from emp order by age desc;

# 3、先按照age升序,再按照salary降序
select * from emp order by age asc, salary desc;

# 4、統計 各部門(分組) 年齡在10歲以上的員工平均工資,並且保留平均工資大於1000的部門,然后對平均工資進行升序序
select post, avg(salary) from emp where age > 10 group by post having avg(salary) > 1000 order by avg(salary);

執行順序:
		- from
		- where 
		- group by 
		- having 
		- select 
    	- order by  # 通過select 查出來的數據再進行排序

9、limit

# limit: 限制結果返回數量
# 應用場景: 類似於博客園首頁的數據展示,每一頁有固定的數量;

# 1、從第一條開始,獲取4條記錄;
select * from emp limit 4;

# 2、limit可以有兩個參數, 參數1:是限制的開始位置, 參數2:是從開始位置展示的條數;
select * from emp limit 0, 4;
select * from emp limit 4, 4;

# 3、查詢工資最高的人的詳細信息
select * from emp order by salary limit 1;

執行順序:
		- from
		- where
		- group by
		- having
		- select 
		- distinct
		- order by 
		- limit

10、正則

# 在編程中,凡是看到reg開頭的,基本上都是跟正則有關
select * from emp where name regexp '^程.*(金|銀|銅|鐵)$';

二 多表查詢

'''
-	多表查詢
		- 關聯查詢
		- 子查詢
'''

創建表與插入數據准備

#建表
create table dep2(
id int,
name varchar(20) 
);

create table emp2(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);

#插入數據
insert into dep2 values
(200,'技術'),
(201,'人力資源'),
(202,'銷售'),
(203,'運營');

insert into emp2(name,sex,age,dep_id) values
('tank','male',17,200),
('egon','female',48,201),
('kevin','male',38,201),
('jason','female',28,202),
('owen','male',18,200),
('sean','female',18,204);


# 注意: 將拆分的表,再拼接到一起進行查詢, 可以通過一張表查另一張表的數據;

1、關聯查詢

# 左表的一條記錄與右表的一條記錄都對應一遍稱之為 --> "笛卡爾積"   PS: 百度科普
# 將所有的數據都對應了一遍,雖然不合理但是其中有合理的數據,現在我們需要做的就是找出合理的數據

# 一 比較麻煩的表關聯
1、查詢員工以及所在部門的信息;
# 將兩張表合並,並且根據id字段去判斷
select * from emp2, dep2 where emp2.dep_id = dep2.id;

2、查詢部門為技術部的員工及部門信息
select * from emp2, dep2 where emp2.dep_id = dep2.id and dep2.name = '技術';


# 二 將兩張表關聯到一起的操作,有專門對應的方法
1、inner join
# 1、內連接:只取兩張表有對應關系的記錄
select * from emp2 inner join dep2 on emp2.dep_id = dep2.id;
select * from emp2 inner join dep2 on emp2.dep_id = dep2.id and dep2.name = '技術';

2、left join
# 2、左連接: 在內連接的基礎上保留左表沒有對應關系的記錄
select * from emp2 left join dep2 on emp2.dep_id = dep2.id;

3、right join
# 3、右連接: 在內連接的基礎上保留右表沒有對應關系的記錄
select * from emp2 right join dep2 on emp2.dep_id = dep2.id;

4、union
# 4、全連接:在內連接的基礎上保留左、右面表沒有對應關系的的記錄
select * from emp2 left join dep2 on emp2.dep_id = dep2.id
union
select * from emp2 right join dep2 on emp2.dep_id = dep2.id;

2、子查詢

# 子查詢就是將一個查詢語句的結果用括號括起來,當做另一個查詢語句的條件去用

# 1.查詢部門是技術或者人力資源的員工信息
'''
先獲取技術部和人力資源的id號,再去員工表里根據前面的id篩選出符合要求的員工信息;
'''
select * from emp2 where dep_id in (select id from dep2 where name='技術' or name='人力資源');


# 2.每個部門最新入職的員工 思路:先查每個部門最新入職的員工,再按部門對應上聯表查詢
# 查第一張emp表
select t1.id, t1.name, t1.hire_date, t1.post, t2.* 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;

'''
as:
		- 可以給表起別名
		- 可以給查出來的虛擬表起別名
		- 可以給字段起別名
'''


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM