1. 程式人生 > 其它 >37.基本查詢語句與方法 多表查詢

37.基本查詢語句與方法 多表查詢

1.單表查詢:
1.前期表準備:
create table 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_commment 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
('jason','male',18,'20170301','張江第一帥形象代言',7300.33,401,1), #以下是教學部
('egon','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('tank','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jerry','female',18,'20110211','teacher',9000,401,1),
('nick','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.語法執行順序:
0.初識查詢語句:
select id,name from emp where id>3 and id<=6;
先後順序:
from 從表中獲得資料
where 根據約束條件匹配
select 返回匹配結果
1.from
select * from emp\G;
當表字段特別多的時候 結果排版可能會出現混亂現象,"\G"來規範查詢結果
2.where 當什什麼時候

# 1.查詢id大於等於3小於等於6的資料
select id,name 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 salary = 20000 or salary = 18000 or salary = 17000;
select * from emp where salary in (20000,18000,17000); # 簡寫
3.group by 分組
select * from emp group by post ;# 分組後取出的是每個組的第一條資料
select id,name,sex from emp group by post; # 驗證
"""
設定sql_mode為only_full_group_by,意味著以後但凡分組,只能取到分組的依據,
不應該在去取組裡面的單個元素的值,那樣的話分組就沒有意義了,因為不分組就是對單個元素資訊的隨意獲取
"""

set global sql_mode='strict_trans_tables,only_full_group_buy';
# 重新連結客戶端
select * from emp group by post; # 報錯
select id,name,sex from emp group by post; # 報錯
select post 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;
# 每個部門的人數
select post,count(id) from emp group by post;
# 3.查詢分組之後的部門名稱和每個部門下所有的學生姓名
group_concat (分組之後用)不僅可以用來顯示除分組外欄位還有拼接字串的作用
select post,group_concat(name) from emp group by post;
# 4.補充concat(不分組時用)拼接字串達到更好的顯示效果 as語法使用
select name as 姓名,salary as 薪資 from emp;
select concat("NAME: ",name) as 姓名,concat("SAL: ",salary) as 薪資 from emp;

# 補充as語法 即可以給欄位起別名也可以給表起
select emp.id,emp.name from emp as t1; # 報錯 因為表名已經被你改成了t1
select t1.id,t1.name from emp as t1;

關鍵字where group by同時出現的情況下,group by必須在where之後
# where先對整張表進行一次篩選,如何group by再對篩選過後的表進行分組
# 如何驗證where是在group by之前執行而不是之後 利用聚合函式 因為聚合函式只能在分組之後才能使用
# 語法順序
select
from
where
group by
# 再識執行順序
from
where
group by
select


4.having 與分組配合時使用 與where作用相同
select 查詢欄位1,..查詢欄位n from 表名 where 過濾條件 group by 分組依據 having 過濾條件;
執行順序
from
where
group by
having
select
ps:having的語法格式與where一致,只不過having是在分組之後進行的過濾,即where雖然不能用聚合函式,但是having可以!
1、統計各部門年齡在30歲以上的員工平均工資,並且保留平均工資大於10000的部門
select post,avg(salary) from emp where age>30 group by post having avg(salary) >1000;
5.distinct 去重
作用: 對有重複展示的資料進行去重操作
SQL語句:
select distinct id ,age from emp;
執行順序:
from
where
group by
having
select
distinct
6.order by 排序
asc 升序:
desc 降序:
預設升序排
select *from emp order by salary asc;
降排序
select * from emp order by salary desc;
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
order by
select
distinct

7.limit 翻頁
# 限制展示條數
select *from emp limit 3;
select * from emp order by salary desc limit 1;
執行順序:
from
where
group by
having
order by
limit
select
distinct
select * from emp limit 10,5;

ps:
1.當limit只有一個引數的時候
表示的是隻展示幾條
2.當limit有兩個引數的時候
第一個引數表示的起始位置
第二個引數表示從起始位置開始往後展示的條數
8.正則
select * from emp where name regexp '^j.*(n|y)$';

2.多表查詢
1.開始創表前,即推導
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
('jason','male',18,200),
('egon','female',48,201),
('kevin','male',38,201),
('nick','female',28,202),
('owen','male',18,200),
('jerry','female',18,204)
;

# 當初為什麼我們要分表,就是為了方便管理,在硬碟上確實是多張表,但是到了記憶體中我們應該把他們再拼成一張表進行查詢才合理

表查詢


select * from emp,dep; # 左表一條記錄與右表所有記錄都對應一遍>>>笛卡爾積

# 將所有的資料都對應了一遍,雖然不合理但是其中有合理的資料,現在我們需要做的就是找出合理的資料

# 查詢員工及所在部門的資訊
select * from emp,dep where emp.dep_id = dep.id;
# 查詢部門為技術部的員工及部門資訊
select * from emp,dep where emp.dep_id = dep.id and dep.name = '技術';


2.連表操作查詢
inner join 內連線
left join 左連線
right join 右連線
union 全連線

# 將兩張表關聯到一起的操作,有專門對應的方法
# 1、內連線:只取兩張表有對應關係的記錄
select * from emp inner join dep on emp.dep_id = dep.id;
2、左連線: 在內連線的基礎上保留左表沒有對應關係的記錄
select * from emp left join dep on emp.dep_id = dep.id;

3.右連線:在內連線的基礎上保留右表沒有對應關係的記錄
select * from emp right join dep on emp.dep_id = dep.id;
4、全連線:在內連線的基礎上保留左、右面表沒有對應關係的的記錄
select * from emp right join dep on emp.dep_id = dep.id;
3.子查詢
將一個表的查詢結果作為另一個查詢的sql語句的查詢條件
1.查詢部門是技術或者人力資源的員工資訊
"""
先獲取技術部和人力資源部的id號,再去員工表裡面根據前面的id篩選出符合要求的員工資訊
"""
select * from emp where dep_id in (select id from dep where name = "技術" or name = "人力資源");
"""
記住一個規律,表的查詢結果可以作為其他表的查詢條件,也可以通過其別名的方式把它作為一張虛擬表去跟其他表做關聯查詢
"""
別名
可以給表起別名
可以給查詢出來的虛擬表起別名
可以給欄位起別名

# exist(瞭解)
EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄,
而是返回一個真假值,True或False。
當返回True時,外層查詢語句將進行查詢
當返回值為False時,外層查詢語句不進行查詢。
select * from emp
where exists
(select id from dep where id > 203);