MySQL入門(四)
distinct:去重
mysql>:
create table t1(
id int,
x int,
y int
);
mysql>: insert into t1 values(1, 1, 1), (2, 1, 2), (3, 2, 2), (4, 2, 2);
mysql>: select distinct * from t1; # 全部數據
mysql>: select distinct x, y from t1; # 結果 1,1 1,2 2,2
mysql>: select distinct y from t1; # 結果 1 2
# 總結:distinct對參與查詢的所有字段,整體去重(所查的全部字段的值都相同,才認為是重復數據)
準備數據
CREATE TABLE `emp` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
`gender` enum('男','女','未知') NULL DEFAULT '未知',
`age` int(0) NULL DEFAULT 0,
`salary` float NULL DEFAULT 0,
`area` varchar(20) NULL DEFAULT '中國',
`port` varchar(20) DEFAULT '未知',
`dep` varchar(20),
PRIMARY KEY (`id`)
);
INSERT INTO `emp` VALUES
(1, 'yangsir', '男', 42, 10.5, '上海', '浦東', '教職部'),
(2, 'engo', '男', 38, 9.4, '山東', '濟南', '教學部'),
(3, 'jerry', '女', 30, 3.0, '江蘇', '張家港', '教學部'),
(4, 'tank', '女', 28, 2.4, '廣州', '廣東', '教學部'),
(5, 'jiboy', '男', 28, 2.4, '江蘇', '蘇州', '教學部'),
(6, 'zero', '男', 18, 8.8, '中國', '黃浦', '咨詢部'),
(7, 'owen', '男', 18, 8.8, '安徽', '宣城', '教學部'),
(8, 'jason', '男', 28, 9.8, '安徽', '巢湖', '教學部'),
(9, 'ying', '女', 36, 1.2, '安徽', '蕪湖', '咨詢部'),
(10, 'kevin', '男', 36, 5.8, '山東', '濟南', '教學部'),
(11, 'monkey', '女', 28, 1.2, '山東', '青島', '教職部'),
(12, 'san', '男', 30, 9.0, '上海', '浦東', '咨詢部'),
(13, 'san1', '男', 30, 6.0, '上海', '浦東', '咨詢部'),
(14, 'san2', '男', 30, 6.0, '上海', '浦西', '教學部'),
(15, 'ruakei', '女', 67, 2.501, '上海', '陸家嘴', '教學部');
常用函數
"""
拼接:concat() | concat_ws()
大小寫:upper() | lower()
浮點型操作:ceil() | floor() | round()
整型:可以直接運算
"""
mysql>: select name,area,port from emp;
mysql>: select name as 姓名, concat(area,'-',port) 地址 from emp; # 上海-浦東
mysql>: select name as 姓名, concat_ws('-',area,port,dep) 信息 from emp; # 上海-浦東-教職部
mysql>: select upper(name) 姓名大寫,lower(name) 姓名小寫 from emp;
mysql>: select id,salary,ceil(salary)上薪資,floor(salary)下薪資,round(salary)入薪資 from emp;
mysql>: select name 姓名, age 舊年齡, age+1 新年齡 from emp;
條件:where
# 多條件協調操作導入:where 奇數 [group by 部門 having 平均薪資] order by [平均]薪資 limit 1
mysql>: select * from emp where id<5 limit 1; # 正常
mysql>: select * from emp limit 1 where id<5; # 異常,條件亂序
# 判斷規則
"""
比較符合:> | < | >= | <= | = | !=
區間符合:between 開始 and 結束 | in(自定義容器)
邏輯符合:and | or | not
相似符合:like _|%
正則符合:regexp 正則語法
"""
mysql>: select * from emp where salary>5;
mysql>: select * from emp where id%2=0;
mysql>: select * from emp where salary between 6 and 9;
mysql>: select * from emp where id in(1, 3, 7, 20);
# _o 某o | __o 某某o | _o% 某o* (*是0~n個任意字符) | %o% *o*
mysql>: select * from emp where name like '%o%';
mysql>: select * from emp where name like '_o%';
mysql>: select * from emp where name like '___o%';
# sql只支持部分正則語法
mysql>: select * from emp where name regexp '.*\d'; # 不支持\d代表數字,認為\d就是普通字符串
mysql>: select * from emp where name regexp '.*[0-9]'; # 支持[]語法
分組與篩選:group by | having
where與having
# 表象:在沒有分組的情況下,where與having結果相同
# 重點:having可以對 聚合結果 進行篩選
mysql>: select * from emp where salary > 5;
mysql>: select * from emp having salary > 5;
mysql>: select * from emp where id in (5, 10, 15, 20);
mysql>: select * from emp having id in (5, 10, 15, 20);
聚合函數
"""
max():最大值
min():最小值
avg():平均值
sum():和
count():記數
group_concat():組內字段拼接,用來查看組內其他字段
"""
分組查詢 group by
# 修改my.ini配置重啟mysql服務
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
# 在sql_mode沒有 ONLY_FULL_GROUP_BY 限制下,可以執行,但結果沒有意義
# 有 ONLY_FULL_GROUP_BY 限制,報錯
mysql>: select * from emp group by dep;
# 分組后,表中數據考慮范圍就不是 單條記錄,因為每個分組都包含了多條記錄,參照分組字段,對每個分組中的 多條記錄 統一處理
# eg: 按部門分組,每個部門都有哪些人、最高的薪資、最低的薪資、平均薪資、組里一共有多少人
# 將多條數據統一處理,這種方式就叫 聚合
# 每個部門都有哪些人、最高的薪資、最低的薪資、平均薪資 都稱之為 聚合結果 - 聚合函數操作的結果
# 注:參與分組的字段,也歸于 聚合結果
mysql>:
select
dep 部門,
group_concat(name) 成員,
max(salary) 最高薪資,
min(salary) 最低薪資,
avg(salary) 平均薪資,
sum(salary) 總薪資,
count(gender) 人數
from emp group by dep;
mysql>: select
dep 部門,
max(age) 最高年齡
from emp group by dep;
# 總結:分組后,查詢條件只能為 分組字段 和 聚合函數操作的聚合結果
分組后的having
mysql>:
select
dep 部門,
group_concat(name) 成員,
max(salary) 最高薪資,
min(salary) 最低薪資,
avg(salary) 平均薪資,
sum(salary) 總薪資,
count(gender) 人數
from emp group by dep;
# 最低薪資小于2
mysql>:
select
dep 部門,
group_concat(name) 成員,
max(salary) 最高薪資,
min(salary) 最低薪資,
avg(salary) 平均薪資,
sum(salary) 總薪資,
count(gender) 人數
from emp group by dep having min(salary)<2;
# having可以對 聚合結果 再進行篩選,where不可以
排序
# order by 主排序字段 [asc|desc], 次排序字段1 [asc|desc], ...次排序字段n [asc|desc]
限制 limit
# 語法:limit 條數 | limit 偏移量,條數
mysql>: select name, salary from emp where salary<8 order by salary desc limit 1;
mysql>: select * from emp limit 5,3; # 先偏移5條滿足條件的記錄,再查詢3條
連表查詢
笛卡爾積
# 笛卡爾積: 集合 X{a, b} * Y{o, p, q} => Z{{a, o}, {a, p}, {a, q}, {b, o}, {b, p}, {b, q}}
mysql>: select * from emp, dep;
# 總結:是兩張表 記錄的所有排列組合,數據沒有利用價值
內連接:inner join on
# 關鍵字:inner join on
# 語法:from A表 inner join B表 on A表.關聯字段=B表.關聯字段
mysql>:
select
emp.id,emp.name,salary,dep.name,work
from emp inner join dep on emp.dep_id = dep.id
order by emp.id;
# 總結:只保留兩個表有關聯的數據
左連接:left join on
# 關鍵字:left join on
# 語法:from 左表 left join 右表 on 左表.關聯字段=右表.關聯字段
mysql>:
select
emp.id,emp.name,salary,dep.name,work
from emp left join dep on emp.dep_id = dep.id
order by emp.id;
# 總結:保留左表的全部數據,右表有對應數據直接連表顯示,沒有對應關系空填充
右連接:right join on
# 關鍵字:right join on
# 語法:from A表 right join B表 on A表.關聯字段=B表關聯字段
mysql>:
select
emp.id,emp.name,salary,dep.name,work
from emp right join dep on emp.dep_id = dep.id
order by emp.id;
# 總結:保留右表的全部數據,左表有對應數據直接連表顯示,沒有對應關系空填充
左右可以相互轉化
mysql>:
select
emp.id,emp.name,salary,dep.name,work
from emp right join dep on emp.dep_id = dep.id
order by emp.id;
mysql>:
select
emp.id,emp.name,salary,dep.name,work
from dep left join emp on emp.dep_id = dep.id
order by emp.id;
# 總結:更換一下左右表的位置,相對應更換左右連接關鍵字,結果相同
全連接:union(并集)
mysql>:
select
emp.id,emp.name,salary,dep.name,work
from emp left join dep on emp.dep_id = dep.id
union
select
emp.id,emp.name,salary,dep.name,work
from emp right join dep on emp.dep_id = dep.id
order by id;
# 總結:左表右表數據都被保留,彼此有對應關系正常顯示,彼此沒有對應關系均空填充對方