目錄
數據庫查詢語句
一、單表查詢
增刪改查回顧
增:
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稍有特殊(書寫位置),條件的種類可以不全。
可以缺失,但不能亂序
常用函數
拼接:concat() | concat_ws()
大小寫:upper() | lower()
浮點型操作:ceil() | floor() | round()
整型:可以直接運算
select name 姓名,age 年齡 ,CONCAT_WS('-',area,port,dep) 地址, # 用-拼接記錄
UPPER(name) 大寫姓名,LOWER(name) 小寫姓名,
salary 工資,
CEIL(salary) 向上, # 向上取整
FLOOR(salary) 向下, # 向下取整
ROUND(salary) 四舍五入
from emp
ORDER BY salary desc;
條件:while
# 判斷規則
"""
比較符合:> | < | >= | <= | = | !=
區間符合:between 開始 and 結束 | in(自定義容器)
邏輯符合:and | or | not
相似符合:like _|%
正則符合:regexp 正則語法
"""
# limit [n,]m: # 偏移n條記錄后再查詢前m條記錄
select salary from emp limit 2,2;
# 運算符
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;
聚合函數
"""
max():最大值
min():最小值
avg():平均值
sum():和
count():記數
group_concat():組內字段拼接,用來查看組內其他字段
"""
分組查詢:group by
# 在sql_mode沒有 ONLY_FULL_GROUP_BY 限制下,可以執行,但結果沒有意義
# 有 ONLY_FULL_GROUP_BY 限制,報錯
mysql>: select * from emp group by dep;
# 分組后,表中數據考慮范圍就不是 單條記錄,因為每個分組都包含了多條記錄,參照分組字段,對每個分組中的 多條記錄 統一處理
# eg: 按部門分組,每個部門都有哪些人、最高的薪資、最低的薪資、平均薪資、組里一共有多少人
# 將多條數據統一處理,這種方式就叫 聚合
# 每個部門都有哪些人、最高的薪資、最低的薪資、平均薪資 都稱之為 聚合結果 - 聚合函數操作的結果
# 注:參與分組的字段,也歸於 聚合結果
SELECT
dep 部門,
GROUP_CONCAT(name) 成員,
MAX(salary) 最高薪資,
MIN(salary) 最低薪資,
AVG(salary) 平均工資,
SUM(salary) 總薪資,
count(name) 人數
from emp GROUP BY dep;
分組后的having
having可以對 聚合結果 進行篩選,where不可以,會報錯
SELECT
dep 部門,
GROUP_CONCAT(name) 成員,
MAX(salary) 最高薪資,
MIN(salary) 最低薪資,
AVG(salary) 平均工資,
SUM(salary) 總薪資,
count(name) 人數
from emp GROUP BY dep having min(salary)<2;
三、排序
排序規則
order by 主排序字段 [asc|desc], 次排序字段1 [asc|desc], ...次排序字段n [asc|desc]
排序優先級從左到右遞減,主排序字段優先級最高
未分組狀態下
# 按年齡升序
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;
分組狀態下
SELECT
dep 部門,
GROUP_CONCAT(name) 成員,
MAX(salary) 最高薪資,
MIN(salary) 最低薪資,
AVG(salary) 平均工資,
SUM(salary) 總薪資,
count(name) 人數
from emp GROUP BY dep ORDER BY 最高薪資 desc;
四、連表查詢
連接
# 連接:將有聯系的多張表通過關聯(有聯系就行,不一定是外鍵)字段,進行連接,形參一張大表
# 連表查詢:在大表的基礎上進行查詢,就稱之為連表查詢
# 將表與表建立連接的方式有四種:內連接、左連接、右連接、全連接
建表
create table dep(
id int primary key auto_increment,
name varchar(16),
work varchar(16)
);
create table emp(
id int primary key auto_increment,
name varchar(16),
salary float,
dep_id int
);
insert into dep values(1, '市場部', '銷售'), (2, '教學部', '授課'), (3, '管理部', '開車');
insert into emp(name, salary, dep_id) values('egon', 3.0, 2),('yanghuhu', 2.0, 2),('sanjiang', 10.0, 1),('owen', 88888.0, 2),('liujie', 8.0, 1),('yingjie', 1.2, 0);
笛卡爾積
# 笛卡爾積: 集合 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
# 語法: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;
# 總結:只保留兩個表有關聯的數據
左連接
####
```mysql
# 關鍵字: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
# 語法: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;
# 總結:更換一下左右表的位置,相對應更換左右連接關鍵字,結果相同
全連接
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;
# 總結:左表右表數據都被保留,彼此有對應關系正常顯示,彼此沒有對應關系均空填充對方
五、一對一與一對多
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 book. NAME 書名, GROUP_CONCAT(author. NAME) 學生姓名, price 價格 FROM book JOIN author_book ON book.id = author_book.book_id JOIN author ON author_book.author_id = author.id GROUP BY 書名 ORDER BY price;