條件
from / where / group by / having distinct / order by / limit
- 使用這些條件可以按照需求任意選擇,但是順序必須按照上面的順序來
- 特殊點:distinct是放在最前面的,但是執行邏輯是上面的順序
去重:distinct
- select distinct * from 表;
- 對於你查詢出的所有記錄,所有字段必須完全一模一樣才會去重
- 可以改為 任意字段
常用函數
- concat()/concat_ws()
- 拼接
- concat(字段,['拼接符號'],字段)
- 將字段按照你寫的格式拼接
- concat_ws('拼接符號',字段n)
- 所有字段按照第一拼接符號拼接
- upper()/lower()
- upper()將字符串都變成大寫
- lower()將字符串都變成小寫
- ceil()/floor()/round()
- ceil(浮點型字段)
- 向上取整
- floor(浮點型字段)
- 向下取整
- round(浮點型字段)
- 小於0.5的舍去
- 大於0.5的進一位
- 整型可以使用運算符直接運算
案例
"""
拼接: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 判斷規則;
- 篩選出符合規則的記錄
- 判斷規則
- 比較符合
- > < >= <= = !=
- 區間符合
- between 開始 and 結束
- 在滿足開始和結束中間都符合
- in (自定義容器)
- 只要在里面的都符合
- 邏輯符合
- and or not
- 相似符合
- like _或者%
- _表示代替一個任意字符
- %表示代替任意個任意字符
- 正則符合
- regexp 正則語法
- 支持部分正則語法
案例
# 多條件協調操作導入: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
- 首先要知道having也是用來篩選的
- 在不分組的情況下,使用where 和 having是一樣的
- 並且,where和having的使用方式完全一致
- PS:having可以對聚合結果進行篩選,還可以對分組的數據進行篩選
- PS:where可以分組前使用
# 表象:在沒有分組的情況下,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():組內字段拼接,用來查看組內其他字段
- 無法設置拼接方式默認以,連接
""" 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; # 總結:分組后,查詢條件只能為 分組字段 和 聚合函數操作的聚合結果
- 修改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 限制,報錯 - 分組后的查詢就不是單條記錄了,而是一組一組的記錄,對每組記錄做同一處理 - 用聚合函數來處理這些數據
-
分組后的having
having可以對 聚合結果 再進行篩選,where不可以
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不可以
-
聯合分組
- group by 字段1,...,字段n
- 將所有字段的結果看作一個整體,進而來進行分組
排序
-
排序規則
# order by 主排序字段 [asc|desc], 次排序字段1 [asc|desc], ...次排序字段n [asc|desc]
- order by 主排序字段 [asc/desc][,次排序字段 [asc/desc]...]
- asc 升序排序,可以不寫,默認升序
- desc 降序排序
- order by 主排序字段 [asc/desc][,次排序字段 [asc/desc]...]
-
未分組狀態下
mysql>: select * from emp; # 按年齡升序 mysql>: select * from emp order by age asc; # 按薪資降序 mysql>: select * from emp order by salary desc; # 按薪資降序,如果相同,再按年齡降序 mysql>: select * from emp order by salary desc, age desc; # 按齡降序,如果相同,再按薪資降序 mysql>: select * from emp order by age desc, salary desc;
-
分組狀態下
mysql>: select dep 部門, group_concat(name) 成員, max(salary) 最高薪資, min(salary) 最低薪資, avg(salary) 平均薪資, sum(salary) 總薪資, count(gender) 人數 from emp group by dep; # 最高薪資降序 mysql: select dep 部門, group_concat(name) 成員, max(salary) 最高薪資, min(salary) 最低薪資, avg(salary) 平均薪資, sum(salary) 總薪資, count(gender) 人數 from emp group by dep order by 最高薪資 desc;
-
限制 limit
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條
單表查詢
"""
增:
insert [into]
[數據庫名.]表名[(字段1[, ..., 字段n])]
values
(數據1[, ..., 數據n])[, ..., (數據1[, ..., 數據n])];
刪:
delete from [數據庫名.]表名 [條件];
改:
updata [數據庫名.]表名 set 字段1=值1[, ..., 字段n=值n] [條件];
查:
select [distinct] 字段1 [[as] 別名1],...,字段n [[as] 別名n] from [數據庫名.]表名 [條件];
"""
# 條件:from、where、group by、having、distinct、order by、limit => 層層篩選后的結果
# 注:一條查詢語句,可以擁有多種篩選條件,條件的順序必須按照上方順序進行逐步篩選,distinct稍有特殊(書寫位置),條件的種類可以不全
# 可以缺失,但不能亂序
增
- insert [into]
[數據庫名].表名[字段n]
vlaues
(數據n);- 數據與字段要一一對應
- 如果字段沒有寫表示所有的數據都要填寫
刪
- delete from 數據庫名].表名 [條件];
改
- updata [數據庫名.]表名 set 字段1=值1[, ..., 字段n=值n] [條件];
查
- updata [數據庫名.]表名 set 字段1=值1[, ..., 字段n=值n] [條件];
連表查詢
連接
# 連接:將有聯系的多張表通過關聯(有聯系就行,不一定是外鍵)字段,進行連接,形參一張大表
# 連表查詢:在大表的基礎上進行查詢,就稱之為連表查詢
# 將表與表建立連接的方式有四種:內連接、左連接、右連接、全連接
- 建立表與表間的聯系,可以是兩張及以上
- 不要求外鍵,有聯系就行
- 連接后是一大張包所有表字段的大表—實際上是多張表
- 連表查詢
- 在張大表的基礎上進行查詢叫做連表查詢
- 建立表與表連接的方式有四種
- 內連接
- 左連接
- 右連接
- 全連接
笛卡爾積
# 笛卡爾積: 集合 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;
# 總結:是兩張表 記錄的所有排列組合,數據沒有利用價值
- select * from 表1 , 表2;
- 將兩張表的記錄進行全排列
一對多
-
內連接
# 關鍵字: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; # 總結:只保留兩個表有關聯的數據
- from A表 [inner] join B表 on A表.關聯字段=B表關聯字段
-
左連接
# 關鍵字: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; # 總結:保留左表的全部數據,右表有對應數據直接連表顯示,沒有對應關系空填充
- from A表 left join B表 on A表.關聯字段=B表關聯字段
-
右連接
# 關鍵字: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; # 總結:保留右表的全部數據,左表有對應數據直接連表顯示,沒有對應關系空填充
- 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 dep left join emp on emp.dep_id = dep.id order by emp.id; # 總結:更換一下左右表的位置,相對應更換左右連接關鍵字,結果相同
- 交AB表位置和left/right關鍵字
- 形成的新連接是一模一樣的
-
全連接
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; # 總結:左表右表數據都被保留,彼此有對應關系正常顯示,彼此沒有對應關系均空填充對方
- select 表的字段名
from A表 left join B表 on A表.關聯字段=B表關聯字段
union
select 表的字們
from A表 right join B表 on A表.關聯字段=B表關聯字段- 因為mysql了不支持全連接,所以兩張表的左右連接和union實現全連接
- 注意:兩個左右連接必都先select形成一張新表,再用union連接成一張信新表
- 之后的操作只能對新表來完成
- PS:兩個select中的字段們必須完全一致,連順序也要一樣
- select 表的字段名
一對一與一對多情況一致
# 創建一對一 作者與作者詳情 表
create table author(
id int,
name varchar(64),
detail_id int
);
create table author_detail(
id int,
phone varchar(11)
);
# 填充數據
insert into author values(1, 'Bob', 1), (2, 'Tom', 2), (3, 'ruakei', 0);
insert into author_detail values(1, '13344556677'), (2, '14466779988'), (3, '12344332255');
# 內連
select author.id,name,phone from author join author_detail on author.detail_id = author_detail.id order by author.id;
# 全連
select author.id,name,phone from author left join author_detail on author.detail_id = author_detail.id
union
select author.id,name,phone from author right join author_detail on author.detail_id = author_detail.id
order by id;
多對多:兩表兩表建立連接
# 在一對一基礎上,建立 作者與書 的多對多關系關系
# 利用之前的作者表
create table author(
id int,
name varchar(64),
detail_id int
);
insert into author values(1, 'Bob', 1), (2, 'Tom', 2), (3, 'ruakei', 0);
# 創建新的書表
create table book(
id int,
name varchar(64),
price decimal(5,2)
);
insert into book values(1, 'python', 3.66), (2, 'Linux', 2.66), (3, 'Go', 4.66);
# 創建 作者與書 的關系表
create table author_book(
id int,
author_id int,
book_id int
);
# 數據:author-book:1-1,2 2-2,3 3-1,3
insert into author_book values(1,1,1),(2,1,2),(3,2,2),(4,2,3),(5,3,1),(6,3,3);
# 將有關聯的表一一建立連接,查詢所以自己所需字段
select book.name, book.price, author.name, author_detail.phone from book
join author_book on book.id = author_book.book_id
join author on author_book.author_id = author.id
left join author_detail on author.detail_id = author_detail.id;
- 前提兩張被關系表個關系表都創建完成了【表里有數據了】
- 將有關聯的表一一建立連接,查詢所以自己所需字段
- select 表的字段 from A表
join 關系表 on A表.關聯字段=關系表.關聯字段
join B表 on 關系表.關聯字段=B表.關聯呢字段; - join可以寫多個,但內鏈連接會導致數據的丟失
子查詢——增刪改都是對表的數據進行修改,所以子查詢不要和被修改的表同表
增
- insert into 表 select 子查詢
刪
- delete from 表 條件是子查詢
改
- update 表 set 字段=值 條件是子查詢
查
- select 字段 from 表 條件是子查詢