MySQL的基礎知識
資料庫基礎知識
1.為什么要使用資料庫
-
~ 解決資料持久化問題
- 高效的管理資料(增刪改查) ### 2.資料庫的分類:
- 關系型資料庫
? - 理論基礎:關系代數
? - 具體表象:二維表
? ~ 行:記錄
? ~ 列:欄位
? - 編程語言:SQL(結構化查詢語言)
? ~ DDL - 資料定義語言 —> create / drop / alter
? ~ DML - 資料操作語言 —> insert / delete / update
? ~ DQL - 資料查詢語言 —> select
-
? ~ DCL - 資料控制語言 —> grant / revoke
- 非關系型資料庫(NoSQL / NewSQL)
? - MongoDB —> 檔案資料庫
? - Redis —> KV資料庫
3.相關術語
-
~ DB - database
-
DBA - database administrator
-
DBMS - database management system
-
DBS - database system
### 4.使用MySQL
-
查看所有資料庫:
show databases; -
切換資料庫:
use school; -
查看資料庫下所有的表:
show tables; -
查看所有的字符集(編碼):
show charset; -
查看所有的校對(排序)規則:
show collation; -
查看所有的引擎:
show engines; -
創建/洗掉資料庫:
? create schema school default charset utf8mb4;
? create database school default charset utf8mb4 collate utf8mb4_bin;
? create database school default character set utf8mb4;
? drop database if exists school;
~ 創建/洗掉/修改二維表:
? create table tb_student (列名 資料型別 約束條件);
? drop table tb_student;
? alter table tb_student add column ...;
? alter table tb_student drop column ...;
? alter table tb_student modify column ...;
? alter table tb_student change column ...;
? alter table tb_student add constraint ...;
? alter table tb_student drop constraint ...;
? - 主鍵(primary key):能夠唯一確定一條記錄的欄位,
? - 外鍵(foreign key):外來的主鍵(其他表的主鍵),
~ 插入/洗掉/更新資料:
? insert into tb_student (...) values (...);
? insert into tb_student (...) values (...), (...), (...);
? delete from tb_student where stu_id=...;
? delete from tb_student where stu_id in (...);
? update tb_student set ..., ... where stu_id=...;
5.MySQL的資料型別 —> ? data types;
~ 整數:
? - int / integer —> -2^31 ~ 2^31 - 1
? - int unsigned —> 0 ~ 2^32 - 1
? - bigint —> -2^63 ~ 2^63 - 1
? - bigint unsigned —> 0 ~ 2^64 - 1
? - smallint —> -32768 ~ 32767
? - smallint unsigned —> 0 ~ 65535
? - tinyint —> -128 ~ 127
-
? - tinyint unsigned —> 0 ~ 255
- 小數:
? - float / double
? - decimal —> decimal(10,2)
~ 字串:
? - char(N) / varchar(N)
-
? - longtext —> longblob(二進制大物件)—> 4G —> 放資源路徑(URL)
- 時間日期:
? - date / time / datetime(6)
-
? - timestamp —> 1970-1-1 00:00:00
- 布爾型:
? - boolean —> tinyint(1) —> 0 / 1
MySQL常用命令
在powershell視窗中輸入 mysql -u root -p 然后輸入下列命令,前提得保證MySQL服務器是打開的,沒打開請手動打開,
-
查看所有資料庫
show databases; -
查看所有字符集(編碼方式)
show character set; -
查看所有的校對規則(排序)
show collation; -
查看所有的引擎
show engines; -
查看所有的日志檔案
show binary logs; -
查看資料庫下所有的表
show tables; -
獲取幫助
1.查看show命令的幫助,
?show2.查看有哪些幫助內容
?contents3.獲取函式的幫助
?functions4.獲取資料型別的幫助
?data types
SQL 的四種語言
DDL(資料定義語言)
-- 如果存在名為school的資料庫就洗掉它
drop database if exists `school`;
-- 創建名為school的資料庫并設定默認的字符集和排序方式
create database `school` default character set utf8mb4;
-- 切換到school資料庫背景關系環境
use `school`;
-- 創建學院表
create table `tb_college`
(
`col_id` int unsigned auto_increment comment '編號',
`col_name` varchar(50) not null comment '名稱',
`col_intro` varchar(5000) default '' comment '介紹',
primary key (`col_id`)
) engine=innodb comment '學院表';
-- 創建學生表
create table `tb_student`
(
`stu_id` int unsigned not null comment '學號',
`stu_name` varchar(20) not null comment '姓名',
`stu_sex` boolean default 1 comment '性別',
`stu_birth` date not null comment '出生日期',
`stu_addr` varchar(255) default '' comment '籍貫',
`col_id` int unsigned not null comment '所屬學院',
primary key (`stu_id`),
foreign key (`col_id`) references `tb_college` (`col_id`)
) engine=innodb comment '學生表';
-- 創建教師表
create table `tb_teacher`
(
`tea_id` int unsigned not null comment '工號',
`tea_name` varchar(20) not null comment '姓名',
`tea_title` varchar(10) default '助教' comment '職稱',
`col_id` int unsigned not null comment '所屬學院',
primary key (`tea_id`),
foreign key (`col_id`) references `tb_college` (`col_id`)
) engine=innodb comment '老師表';
-- 創建課程表
create table `tb_course`
(
`cou_id` int unsigned not null comment '編號',
`cou_name` varchar(50) not null comment '名稱',
`cou_credit` int not null comment '學分',
`tea_id` int unsigned not null comment '授課老師',
primary key (`cou_id`),
foreign key (`tea_id`) references `tb_teacher` (`tea_id`)
) engine=innodb comment '課程表';
-- 創建選課記錄表
create table `tb_record`
(
`rec_id` bigint unsigned auto_increment comment '選課記錄號',
`sid` int unsigned not null comment '學號',
`cid` int unsigned not null comment '課程編號',
`sel_date` date not null comment '選課日期',
`score` decimal(4,1) comment '考試成績',
primary key (`rec_id`),
foreign key (`sid`) references `tb_student` (`stu_id`),
foreign key (`cid`) references `tb_course` (`cou_id`),
unique (`sid`, `cid`)
) engine=innodb comment '選課記錄表';
DML(資料操作語言)
use school;
-- 插入學院資料
insert into `tb_college`
(`col_name`, `col_intro`)
values
('計算機學院', '計算機學院1958年設立計算機專業,1981年建立計算機科學系,1998年設立計算機學院,2005年5月,為了進一步整合教學和科研資源,學校決定,計算機學院和軟體學院行政班子合并統一運作、實行教學和學生管理獨立運行的模式, 學院下設三個系:計算機科學與技術系、物聯網工程系、計算金融系;兩個研究所:圖象圖形研究所、網路空間安全研究院(2015年成立);三個教學實驗中心:計算機基礎教學實驗中心、IBM技術中心和計算機專業實驗中心,'),
('外國語學院', '外國語學院設有7個教學單位,6個文理兼收的本科專業;擁有1個一級學科博士授予點,3個二級學科博士授予點,5個一級學科碩士學位授權點,5個二級學科碩士學位授權點,5個碩士專業授權領域,同時還有2個碩士專業學位(MTI)專業;有教職員工210余人,其中教授、副教授80余人,教師中獲得中國國內外名校博士學位和正在職攻讀博士學位的教師比例占專任教師的60%以上,'),
('經濟管理學院', '經濟學院前身是創辦于1905年的經濟科;已故經濟學家彭迪先、張與九、蔣學模、胡寄窗、陶大鏞、胡代光,以及當代學者劉詩白等曾先后在此任教或學習,');
-- 插入學生資料
insert into `tb_student`
(`stu_id`, `stu_name`, `stu_sex`, `stu_birth`, `stu_addr`, `col_id`)
values
(1001, '楊過', 1, '1990-3-4', '湖南長沙', 1),
(1002, '任我行', 1, '1992-2-2', '湖南長沙', 1),
(1033, '王語嫣', 0, '1989-12-3', '四川成都', 1),
(1572, '岳不群', 1, '1993-7-19', '陜西咸陽', 1),
(1378, '紀嫣然', 0, '1995-8-12', '四川綿陽', 1),
(1954, '林平之', 1, '1994-9-20', '福建莆田', 1),
(2035, '東方不敗', 1, '1988-6-30', null, 2),
(3011, '林震南', 1, '1985-12-12', '福建莆田', 3),
(3755, '項少龍', 1, '1993-1-25', null, 3),
(3923, '楊不悔', 0, '1985-4-17', '四川成都', 3);
-- 插入老師資料
insert into `tb_teacher`
(`tea_id`, `tea_name`, `tea_title`, `col_id`)
values
(1122, '張三豐', '教授', 1),
(1133, '宋遠橋', '副教授', 1),
(1144, '楊逍', '副教授', 1),
(2255, '范遙', '副教授', 2),
(3366, '韋一笑', default, 3);
-- 插入課程資料
insert into `tb_course`
(`cou_id`, `cou_name`, `cou_credit`, `tea_id`)
values
(1111, 'Python程式設計', 3, 1122),
(2222, 'Web前端開發', 2, 1122),
(3333, '作業系統', 4, 1122),
(4444, '計算機網路', 2, 1133),
(5555, '編譯原理', 4, 1144),
(6666, '演算法和資料結構', 3, 1144),
(7777, '經貿法語', 3, 2255),
(8888, '成本會計', 2, 3366),
(9999, '審計學', 3, 3366);
-- 插入選課資料
insert into `tb_record`
(`sid`, `cid`, `sel_date`, `score`)
values
(1001, 1111, '2017-09-01', 95),
(1001, 2222, '2017-09-01', 87.5),
(1001, 3333, '2017-09-01', 100),
(1001, 4444, '2018-09-03', null),
(1001, 6666, '2017-09-02', 100),
(1002, 1111, '2017-09-03', 65),
(1002, 5555, '2017-09-01', 42),
(1033, 1111, '2017-09-03', 92.5),
(1033, 4444, '2017-09-01', 78),
(1033, 5555, '2017-09-01', 82.5),
(1572, 1111, '2017-09-02', 78),
(1378, 1111, '2017-09-05', 82),
(1378, 7777, '2017-09-02', 65.5),
(2035, 7777, '2018-09-03', 88),
(2035, 9999, '2019-09-02', null),
(3755, 1111, '2019-09-02', null),
(3755, 8888, '2019-09-02', null),
(3755, 9999, '2017-09-01', 92);
DQL(資料查詢語言)
-- 查詢所有學生的所有資訊
select * from tb_student;
select stu_id, stu_name, stu_sex, stu_birth, stu_addr, col_id from tb_student;
-- 查詢所有課程名稱及學分(投影和別名)
select cou_name as 課程名稱, cou_credit as 學分 from tb_course;
-- 查詢所有女學生的姓名和出生日期(篩選)
select stu_name, stu_birth from tb_student where stu_sex=0;
-- 查詢所有80后學生的姓名、性別和出生日期(篩選)
select stu_name, stu_sex, stu_birth from tb_student
where stu_birth>='1980-1-1' and stu_birth<='1989-12-31';
select stu_name, stu_sex, stu_birth from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
-- 補充1:在查詢時可以對列的值進行處理
select
stu_name as 姓名,
case stu_sex when 1 then '男' else '女' end as 性別,
stu_birth as 生日
from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
-- 補充2:MySQL方言(使用資料庫特有的函式)
-- 例如:Oracle中做同樣事情的函式叫做decode
select
stu_name as 姓名,
if(stu_sex, '男', '女') as 性別,
stu_birth as 生日
from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
-- 查詢所有80后女學生的姓名和出生日期
select stu_name, stu_birth from tb_student
where stu_birth between '1980-1-1' and '1989-12-31' and stu_sex=0;
-- 查詢所有的80后學生或女學生的姓名和出生日期
select stu_name, stu_birth from tb_student
where stu_birth between '1980-1-1' and '1989-12-31' or stu_sex=0;
-- 查詢姓“楊”的學生姓名和性別(模糊)
-- 在SQL中通配符%可以匹配零個或任意多個字符
select stu_name, stu_sex from tb_student where stu_name like '楊%';
-- 查詢姓“楊”名字兩個字的學生姓名和性別(模糊)
-- 在SQL中通配符_可以剛剛好匹配一個字符
select stu_name, stu_sex from tb_student where stu_name like '楊_';
-- 查詢姓“楊”名字三個字的學生姓名和性別(模糊)
select stu_name, stu_sex from tb_student where stu_name like '楊__';
-- 查詢名字中有“不”字或“嫣”字的學生的姓名(模糊)
-- 提示:前面帶%的模糊查詢性能基本上都是非常糟糕的
select stu_name from tb_student
where stu_name like '%不%' or stu_name like '%嫣%';
update tb_student set stu_name='岳不嫣' where stu_id=1572;
-- 并集運算
select stu_name from tb_student where stu_name like '%不%'
union
select stu_name from tb_student where stu_name like '%嫣%';
select stu_name from tb_student where stu_name like '%不%'
union all
select stu_name from tb_student where stu_name like '%嫣%';
-- 正則運算式模糊查詢
select stu_name, stu_sex from tb_student where stu_name regexp '^楊.{2}$';
-- 查詢沒有錄入家庭住址的學生姓名(空值)
-- null作任何運算結果也是產生null,null相當于是條件不成立
select stu_name from tb_student where stu_addr is null;
select stu_name from tb_student where stu_addr<=>null;
-- 查詢錄入了家庭住址的學生姓名(空值)
select stu_name from tb_student where stu_addr is not null;
-- 查詢學生選課的所有日期(去重)
select distinct sel_date from tb_record;
-- 查詢學生的家庭住址(去重)
select distinct stu_addr from tb_student where stu_addr is not null;
-- 查詢男學生的姓名和生日按年齡從大到小排列(排序)
-- asc - 升序(從小到大),desc - 降序(從大到小)
select stu_name, stu_birth from tb_student
where stu_sex=1 order by stu_birth asc;
select stu_name, stu_birth from tb_student
where stu_sex=1 order by stu_birth desc;
-- 查詢年齡最大的學生的出生日期(聚合函式) ---> 找出最小的生日
select min(stu_birth) from tb_student;
select
min(stu_birth) as 生日,
floor(datediff(curdate(), min(stu_birth))/365) as 年齡
from tb_student;
-- 查詢年齡最小的學生的出生日期(聚合函式)
select
max(stu_birth) as 生日,
floor(datediff(curdate(), max(stu_birth))/365) as 年齡
from tb_student;
-- 查詢所有考試的平均成績
-- 聚合函式在遇到null值會做忽略的處理
-- 如果做計數操作,建議使用count(*),這樣才不會漏掉空值
select avg(score) from tb_record;
select sum(score) / count(score) from tb_record;
select sum(score) / count(*) from tb_record;
-- 查詢課程編號為1111的課程的平均成績(篩選和聚合函式)
select avg(score) from tb_record where cid=1111;
-- 查詢學號為1001的學生所有課程的平均分(篩選和聚合函式)
select avg(score) from tb_record where sid=1001;
select count(distinct stu_addr) from tb_student where stu_addr is not null;
-- 查詢男女學生的人數(分組和聚合函式)
-- SAC(Split - Aggregate - Combine)
select
if(stu_sex, '男', '女') as 性別,
count(*) as 人數
from tb_student group by stu_sex;
-- 統計每個學院男女學生的人數
select
col_id as 學院,
if(stu_sex, '男', '女') as 性別,
count(*) as 人數
from tb_student group by col_id, stu_sex;
-- 查詢每個學生的學號和平均成績(分組和聚合函式)
select
sid as 學號,
round(avg(score),1) as 平均分
from tb_record group by sid;
-- 查詢平均成績大于等于90分的學生的學號和平均成績
-- 分組以前的資料篩選使用where子句,分組以后的資料篩選使用having子句
select
sid as 學號,
round(avg(score),1) as 平均分
from tb_record
group by sid having 平均分>=90;
-- 查詢年齡最大的學生的姓名(子查詢)
-- 嵌套查詢:把一個查詢的結果作為另外一個查詢的一部分來使用,
select stu_name from tb_student where stu_birth=(
select min(stu_birth) from tb_student
);
-- 查詢年齡最大的學生姓名和年齡(子查詢+運算)
select
stu_name as 姓名,
floor(datediff(curdate(), stu_birth) / 365) as 年齡
from tb_student where stu_birth=(
select min(stu_birth) from tb_student
);
-- 查詢選了兩門以上的課程的學生姓名(子查詢/分組條件/集合運算)
select stu_name from tb_student where stu_id in (
select sid from tb_record group by sid having count(*)>2
);
-- 查詢課程的名稱、學分和授課老師的姓名(連接查詢)
select cou_name, cou_credit, tea_name
from tb_course, tb_teacher
where tb_course.tea_id=tb_teacher.tea_id;
select cou_name, cou_credit, tea_name from tb_course t1
inner join tb_teacher t2 on t1.tea_id=t2.tea_id;
-- 查詢學生姓名、課程名稱以及成績(連接查詢)
select stu_name, cou_name, score
from tb_record, tb_student, tb_course
where stu_id=sid and cou_id=cid and score is not null;
select stu_name, cou_name, score from tb_student
inner join tb_record on stu_id=sid
inner join tb_course on cou_id=cid
where score is not null;
-- 查詢選課學生的姓名和平均成績(子查詢和連接查詢)
select stu_name, avg_score
from tb_student, (select sid, round(avg(score),1) as avg_score
from tb_record group by sid
) tb_temp where stu_id=sid;
-- 分頁查詢
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null
order by score desc limit 5;
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null
order by score desc limit 5 offset 5;
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null
order by score desc limit 5 offset 10; -- 表示 跳過前10個 取五個
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null
order by score desc limit 10,5; -- 表示 跳過前10個 取五個
-- 查詢每個學生的姓名和選課數量(左外連接和子查詢)
-- 內連接:查詢左右兩表滿足連接條件的資料,
-- 外連接
-- 左外連接:確保左表(現在join前面的表)中的所有記錄都能查出來,不滿足連接條件的補充null,
-- 右外連接:確保右表(現在join后面的表)中的所有記錄都能查出來,不滿足連接條件的補充null,
-- 全外連接:確保左表和右表中的所有記錄都能查出來,不滿足連接條件的補充null,
select
stu_name as 姓名,
ifnull(total, 0) as 選課數量
from tb_student left outer join (
select sid, count(*) as total from tb_record group by sid
) tb_temp on stu_id=sid;
-- 右外連接
select t1.stu_id, stu_name, t2.stu_id, total as total
from tb_student t1 right outer join (
select stu_id, count(*) as total from tb_record
group by stu_id
) t2 on t1.stu_id=t2.stu_id;
-- MySQL不支持全外連接
-- 可以通過左外連接與右外連接求并集運算得到全外連接的結果
select t1.stu_id, stu_name, t2.stu_id, total as total
from tb_student t1 left outer join (
select stu_id, count(*) as total from tb_record
group by stu_id
) t2 on t1.stu_id=t2.stu_id
union
select t1.stu_id, stu_name, t2.stu_id, total as total
from tb_student t1 right outer join (
select stu_id, count(*) as total from tb_record
group by stu_id
) t2 on t1.stu_id=t2.stu_id;
DCL(資料控制語言)
-- 創建可以遠程登錄的root賬號并為其指定口令
create user 'root'@'%' identified by '123456';
-- 為遠程登錄的root賬號授權操作所有資料庫所有物件的所有權限并允許其將權限再次賦予其他用戶
grant all privileges on *.* to 'root'@'%' with grant option;
-- 創建名為hellokitty的用戶并為其指定口令
create user 'hellokitty'@'%' identified by '123123';
-- 將對school資料庫所有物件的所有操作權限授予hellokitty
grant all privileges on school.* to 'hellokitty'@'%';
-- 召回hellokitty對school資料庫所有物件的insert/delete/update權限
revoke insert, delete, update on school.* from 'hellokitty'@'%';
##############################################
-- DCL 資料控制語言
-- 創建用戶
create user 'guest' @'10.7.178.%' identified by 'Guest.618';
-- 洗掉用戶
drop user 'guest' @'10.7.178.%';
-- 修改密碼
alter user 'guest' @'10.7.178.%' identified by 'Hellokitty.123';
-- 授權
grant select on hrs.* to 'guest'@'10.7.178.%';
grant insert on hrs.* to 'guest'@'10.7.178.%';
-- 授權所有權限
grant all privileges on hrs.* to 'guest'@'10.7.178.%';
-- 授權所有權限,對于所有物件
grant all privileges on *.* to 'guest'@'10.7.178.%' ;
grant all privileges on *.* to 'guest'@'10.7.178.%' with grant option;
-- 招回權限
revoke insert on hrs.* from 'guest'@'10.7.178.%';
-- 讓權限立即生效
flush privileges
資料庫索引與性能
-- 如何了解SQL陳述句的性能?
-- explain 查看索引性能
-- 索引的本質就相當于是一個排好序的目錄,加速查詢
-- 索引通常要建在經常用戶查詢篩選條件的列上,這樣才能有效的加速查詢
-- 不要濫用索引,因為索引雖然加速了查詢,但是會讓插入資料的操作變得更慢
-- 對于InnoDB引擎來說,索引的底層是一個B+樹,B+樹是一個層次結構
-- 這種結構擁有極好磁盤I/O性能,一個4層的B+樹就能應對10億級的資料體量
-- 對于InnoDB引擎來說,主鍵上默認就會建索引,而且索引就是整張表的資料
-- 這種索引也稱為聚集索引(只能有一個),而我們自己創建的索引都是非聚集索引
-- 1. 查看SQL執行計劃
-- 2. 使用性能剖析系統
explain select * from tb_emp where eno=7800;
explain select * from tb_emp where ename='張三豐';
-- 創建索引
create index idx_emp_ename on tb_emp (ename);
-- 前綴索引
create index idx_emp_ename on tb_emp (ename(1));
-- 索引的覆寫性問題
-- 如果查詢的列沒有被索引覆寫到,就會產生回表現象
-- 如果不希望產生回表現象,那么我們在創建索引時,可以使用復合索引盡可能覆寫查詢需要的所有的列
select eno, ename, job from tb_emp where ename='張三豐';
-- 復合索引 -- 左索引開始
drop index idx_emp_ename_job on tb_emp;
create index idx_emp_ename_job on tb_emp (ename, job);
explain select eno, ename, job from tb_emp where ename='張三豐';
explain select eno, ename, job from tb_emp where ename like '張%' order by ename;
explain select eno, ename, job from tb_emp where ename like '張%' order by sal;
explain select eno, ename, job from tb_emp
where ename='張三豐' and job='總裁';
-- 負向條件無法使用索引優化查詢
explain select eno, ename, job from tb_emp where ename<>'張三豐';
explain select eno, ename, job from tb_emp where ename like '張三%';
-- 模糊查詢如果左邊使用通配符會導致索引失效
explain select eno, ename, job from tb_emp where ename like '%三豐';
-- 在篩選條件中如果使用了函式也會導致索引失效
explain select eno, ename, job from tb_emp where concat(ename, '先生')='張三豐先生';
-- 下面的查詢無法使用復合索引
explain select eno, ename, job from tb_emp
where ename='張三豐' or job='總裁';
-- 下面的查詢無法使用復合索引
explain select eno, ename, job from tb_emp where job='總裁';
-- 洗掉索引
drop index idx_emp_ename on tb_emp;
alter table tb_emp drop index idx_emp_ename;
資料庫存盤與性能
use hrs;
show variables like '%safe%';
-- (存盤)程序:將一系列的SQL組裝到一起編譯存盤起來以備呼叫
-- 洗掉存盤程序
drop procedure if exists sp_upgrade_emp_sal;
-- 創建存盤程序
delimiter $$
create procedure sp_upgrade_emp_sal()
begin
set sql_safe_updates=off;
update tb_emp set sal=sal+200 where dno=10;
update tb_emp set sal=sal+500 where dno=20;
update tb_emp set sal=sal+800 where dno=30;
end $$
delimiter ;
-- 呼叫存盤程序
call sp_upgrade_emp_sal();
delimiter $$
create procedure sp_get_avg_sal(
in dept_no int,
out avg_sal decimal(6,1)
)
begin
select round(avg(sal),1) into avg_sal from tb_emp where dno=dept_no;
end $$
delimiter ;
call sp_get_avg_sal(10, @a);
select @a;
資料庫視圖
-- 視圖
-- 給查詢生成一個快照,以后可以直接通過視圖獲得查詢結果
-- 可以通過視圖將用戶訪問資料的權限限制到具體的列上
-- 創建視圖
create view vw_emp_simple as
select eno, ename, job, dno from tb_emp;
-- 更新視圖實際更新的是視圖對應的原始表的資料
update vw_emp_simple set ename='胡二刀' where eno=1359;
drop user if exists 'wangdachui'@'%';
create user 'wangdachui'@'%' identified
with mysql_native_password by '654321';
-- 授權用戶只能查看視圖
grant select, show view on hrs.vw_emp_simple to 'wangdachui'@'%';
flush privileges;
create view vw_sal_top2 as
select ename, sal, dno from tb_emp t1 where (
select count(*) from tb_emp t2
where t1.dno=t2.dno and t2.sal>t1.sal
)<2 order by dno asc, sal desc;
select * from vw_sal_top2;
create view vw_dept_emp_count as
select dname, ifnull(total, 0) as total from tb_dept t1 left join
(select dno, count(*) as total from tb_emp group by dno) t2
on t1.dno=t2.dno;
-- 不能更新視圖,因為視圖的資料是通過聚合、運算等操作得到的
update vw_dept_emp_count set total=100 where dname='研發2部';
-- 洗掉視圖
drop view vw_dept_emp_count;
資料庫權限授予
use hrs;
-- DCL 資料控制語言
-- 創建用戶
create user 'guest' @'10.7.178.%' identified by 'Guest.618';
-- 洗掉用戶
drop user 'guest' @'10.7.178.%';
-- 修改密碼
alter user 'guest' @'10.7.178.%' identified by 'Hellokitty.123';
-- 授權
grant select on hrs.* to 'guest'@'10.7.178.%';
grant insert on hrs.* to 'guest'@'10.7.178.%';
-- 授權所有權限
grant all privileges on hrs.* to 'guest'@'10.7.178.%';
-- 授權所有權限,對于所有物件
grant all privileges on *.* to 'guest'@'10.7.178.%' ;
grant all privileges on *.* to 'guest'@'10.7.178.%' with grant option;
-- 招回權限
revoke insert on hrs.* from 'guest'@'10.7.178.%';
-- 讓權限立即生效
flush privileges
練習
school庫建立
-- 如果存在名為school的資料庫就洗掉它
drop database if exists `school`;
-- 創建名為school的資料庫并設定默認的字符集和排序方式
create database `school` default character set utf8mb4;
-- 切換到school資料庫背景關系環境
use `school`;
-- 創建學院表
create table `tb_college`
(
`col_id` int unsigned auto_increment comment '編號',
`col_name` varchar(50) not null comment '名稱',
`col_intro` varchar(500) default '' comment '介紹',
primary key (`col_id`)
) engine=innodb auto_increment=1 comment '學院表';
-- 創建學生表
create table `tb_student`
(
`stu_id` int unsigned not null comment '學號',
`stu_name` varchar(20) not null comment '姓名',
`stu_sex` boolean default 1 not null comment '性別',
`stu_birth` date not null comment '出生日期',
`stu_addr` varchar(255) default '' comment '籍貫',
`col_id` int unsigned not null comment '所屬學院',
primary key (`stu_id`),
constraint `fk_student_col_id` foreign key (`col_id`) references `tb_college` (`col_id`)
) engine=innodb comment '學生表';
-- 創建教師表
create table `tb_teacher`
(
`tea_id` int unsigned not null comment '工號',
`tea_name` varchar(20) not null comment '姓名',
`tea_title` varchar(10) default '助教' comment '職稱',
`col_id` int unsigned not null comment '所屬學院',
primary key (`tea_id`),
constraint `fk_teacher_col_id` foreign key (`col_id`) references `tb_college` (`col_id`)
) engine=innodb comment '老師表';
-- 創建課程表
create table `tb_course`
(
`cou_id` int unsigned not null comment '編號',
`cou_name` varchar(50) not null comment '名稱',
`cou_credit` int not null comment '學分',
`tea_id` int unsigned not null comment '授課老師',
primary key (`cou_id`),
constraint `fk_course_tea_id` foreign key (`tea_id`) references `tb_teacher` (`tea_id`)
) engine=innodb comment '課程表';
-- 創建選課記錄表
create table `tb_record`
(
`rec_id` bigint unsigned auto_increment comment '選課記錄號',
`stu_id` int unsigned not null comment '學號',
`cou_id` int unsigned not null comment '課程編號',
`sel_date` date not null comment '選課日期',
`score` decimal(4,1) comment '考試成績',
primary key (`rec_id`),
constraint `fk_record_stu_id` foreign key (`stu_id`) references `tb_student` (`stu_id`),
constraint `fk_record_cou_id` foreign key (`cou_id`) references `tb_course` (`cou_id`),
constraint `uk_record_stu_cou` unique (`stu_id`, `cou_id`)
) engine=innodb comment '選課記錄表';
-- 插入學院資料
insert into `tb_college`
(`col_name`, `col_intro`)
values
('計算機學院', '計算機學院1958年設立計算機專業,1981年建立計算機科學系,1998年設立計算機學院,2005年5月,為了進一步整合教學和科研資源,學校決定,計算機學院和軟體學院行政班子合并統一運作、實行教學和學生管理獨立運行的模式, 學院下設三個系:計算機科學與技術系、物聯網工程系、計算金融系;兩個研究所:圖象圖形研究所、網路空間安全研究院(2015年成立);三個教學實驗中心:計算機基礎教學實驗中心、IBM技術中心和計算機專業實驗中心,'),
('外國語學院', '外國語學院設有7個教學單位,6個文理兼收的本科專業;擁有1個一級學科博士授予點,3個二級學科博士授予點,5個一級學科碩士學位授權點,5個二級學科碩士學位授權點,5個碩士專業授權領域,同時還有2個碩士專業學位(MTI)專業;有教職員工210余人,其中教授、副教授80余人,教師中獲得中國國內外名校博士學位和正在職攻讀博士學位的教師比例占專任教師的60%以上,'),
('經濟管理學院', '經濟學院前身是創辦于1905年的經濟科;已故經濟學家彭迪先、張與九、蔣學模、胡寄窗、陶大鏞、胡代光,以及當代學者劉詩白等曾先后在此任教或學習,');
-- 插入學生資料
insert into `tb_student`
(`stu_id`, `stu_name`, `stu_sex`, `stu_birth`, `stu_addr`, `col_id`)
values
(1001, '留一手', 1, '1990-3-4', '湖南長沙', 1),
(1002, '二麻子', 1, '1992-2-2', '臺灣臺北', 1),
(1033, '法外狂徒張三', 0, '1989-12-3', '北京', 1),
(1572, '四季度', 1, '1993-7-19', '陜西咸陽', 1),
(1378, '五條悟', 0, '1995-8-12', '四川成都', 1),
(1954, '小六子', 1, '1994-9-20', '福建莆田', 1),
(2035, '鬼腳七', 1, '1988-6-30', null, 2),
(3011, '老八', 1, '1985-12-12', '海南海口', 3),
(3755, '九妹', 1, '1993-1-25', null, 3),
(3923, '大十字', 0, '1985-4-17', '貴州貴陽', 3);
-- 插入老師資料
insert into `tb_teacher`
(`tea_id`, `tea_name`, `tea_title`, `col_id`)
values
(1122, '蕭十一郎', '教授', 1),
(1133, '十二月', '副教授', 1),
(1144, '十三姨', '副教授', 1),
(2255, '十四松', '副教授', 2),
(3366, '桃十五', default, 3);
-- 插入課程資料
insert into `tb_course`
(`cou_id`, `cou_name`, `cou_credit`, `tea_id`)
values
(1111, 'Python程式設計', 3, 1122),
(2222, '信號與影像處理', 5, 1122),
(3333, '高等數學', 5, 1122),
(4444, '計算機網路', 3, 1133),
(5555, '離散數學', 3, 1144),
(6666, '資料結構', 5, 1144),
(7777, '資料挖掘', 3, 2255),
(8888, '大資料技術原理與應用', 2, 3366),
(9999, '人工智能導論', 3, 3366);
-- 插入選課資料
insert into `tb_record`
(`stu_id`, `cou_id`, `sel_date`, `score`)
values
(1001, 1111, '2017-09-01', 95),
(1001, 2222, '2019-09-01', 87.5),
(1001, 3333, '2017-09-01', 100),
(1001, 4444, '2018-09-03', null),
(1001, 6666, '2018-09-02', 100),
(1002, 1111, '2017-09-03', 65),
(1002, 5555, '2018-09-01', 42),
(1033, 1111, '2017-09-03', 92.5),
(1033, 4444, '2019-09-01', 78),
(1033, 5555, '2017-09-01', 82.5),
(1572, 1111, '2020-09-02', 78),
(1378, 1111, '2020-09-05', 82),
(1378, 7777, '2020-09-02', 65.5),
(2035, 7777, '2018-09-03', 88),
(2035, 9999, '2019-09-02', null),
(3755, 1111, '2019-09-02', null),
(3755, 8888, '2019-09-02', null),
(3755, 9999, '2017-09-01', 92);
開始查詢
use school;
-- 查詢所有學生的所有資訊
select * from tb_student;
-- 查詢學生的學號、姓名和家庭住址(投影)
select stu_id, stu_name, stu_addr from tb_student;
-- 查詢所有課程的名稱及學分(投影和別名) ---> alias
select cou_name as 課程名稱, cou_credit as 學分 from tb_course;
-- 查詢所有女學生的姓名和出生日期(篩選)
select stu_name, stu_birth from tb_student where stu_sex=0;
-- 查詢所有80后學生的姓名、性別和出生日期(篩選)
select stu_name, stu_sex, stu_birth
from tb_student
where stu_birth>='1980-1-1' and stu_birth<='1989-12-31';
select stu_name, stu_sex, stu_birth
from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
-- 標準SQL的做法
select
stu_name as 姓名,
case stu_sex when 1 then '男' else '女' end as 性別,
stu_birth as 生日
from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
-- MySQL方言 if() 函式 ---> Oracle方言 decode() 函式
select
stu_name as 姓名,
if(stu_sex, '男', '女') as 性別,
stu_birth as 生日
from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
-- 查詢姓“楊”的學生姓名和性別(模糊)
-- 通配符(wildcard)---> % ---> 匹配零個或任意多個字符
select stu_name, stu_sex from tb_student where stu_name like '楊%';
-- 查詢姓“楊”名字兩個字的學生姓名和性別(模糊)
-- 通配符(wildcard)---> _ ---> 精確匹配一個字符
select stu_name, stu_sex from tb_student where stu_name like '楊_';
-- 查詢姓“楊”名字三個字的學生姓名和性別(模糊)
select stu_name, stu_sex from tb_student where stu_name like '楊__';
-- 查詢名字中有“不”字或“嫣”字的學生的姓名(模糊)
select stu_name from tb_student
where stu_name like '%不%' or stu_name like '%嫣%';
select stu_name from tb_student where stu_name like '%嫣%'
union
select stu_name from tb_student where stu_name like '%不%';
-- 基于正則運算式的模糊查詢
select stu_name from tb_student where stu_name regexp '[楊林].{2}';
-- 查詢沒有錄入家庭住址的學生姓名(空值)
select stu_name from tb_student
where stu_addr is null or stu_add='';
select stu_name from tb_student
where stu_addr<=>null or stu_addr='';
-- 查詢錄入了家庭住址的學生姓名(空值)
select stu_name from tb_student
where stu_addr is not null and stu_addr<>'';
-- 查詢學生選課的所有日期(去重)
select distinct sel_date from tb_record;
-- 查詢學生的家庭住址(去重)
select distinct stu_addr from tb_student
where stu_addr is not null;
-- 查詢男學生的姓名和生日按年齡從大到小排列(排序)
-- 升序(從小到大)---> ascending
select stu_name, stu_birth from tb_student
where stu_sex=1
order by stu_birth asc;
-- curdate ---> 獲取當前日期
-- datediff ---> 計算時間差(以天為單位)
-- floor / ceil ---> 向下/上取整
select
stu_name,
stu_birth,
floor(datediff(curdate(), stu_birth)/365) as stu_age
from tb_student
where stu_sex=1
order by stu_age desc;
-- 降序(從大到小)---> descending
select stu_name, stu_birth from tb_student
where stu_sex=1
order by stu_birth desc;
-- 查詢年齡最大的學生的出生日期(聚合函式)
select min(stu_birth) from tb_student;
-- 查詢年齡最小的學生的出生日期(聚合函式)
select max(stu_birth) from tb_student;
-- 查詢編號為1111的課程考試成績的最高分
select max(score) from tb_record where cou_id=1111;
-- 查詢學號為1001的學生考試成績的最低分
select min(score) from tb_record where stu_id=1001;
-- 查詢學號為1001的學生考試成績的平均分
select avg(score) from tb_record where stu_id=1001;
select sum(score) / count(score) from tb_record where stu_id=1001;
-- 查詢學號為1001的學生考試成績的平均分,如果有null值,null值算0分
select sum(score) / count(*) from tb_record where stu_id=1001;
select avg(ifnull(score, 0)) from tb_record where stu_id=1001;
-- ifnull ---> 如果遇到null(空值),將其替換為指定的值
-- 查詢學號為1001的學生考試成績的標準差
select std(score) from tb_record where stu_id=1001;
-- 查詢男女學生的人數(分組和聚合函式)
select
if(stu_sex, '男', '女') as 性別,
count(*) as 人數
from tb_student group by stu_sex;
-- 查詢每個學院男女學生人數
select
col_id as 學院編號,
if(stu_sex, '男', '女') as 性別,
count(*) as 人數
from tb_student group by col_id, stu_sex;
-- 查詢每個學生的學號和平均成績(分組和聚合函式)
select
stu_id as 學號,
round(avg(score), 2) as 平均分
from tb_record group by stu_id;
-- 查詢平均成績大于等于90分的學生的學號和平均成績
select
stu_id as 學號,
round(avg(score), 2) as 平均分
from tb_record
group by stu_id
having 平均分>=90;
-- 查詢1111、2222、3333三門課程平均成績大于等于90分的學生的學號和平均成績
select
stu_id as 學號,
round(avg(score), 2) as 平均分
from tb_record
where cou_id in (1111, 2222, 3333)
group by stu_id
having 平均分>=90;
-- 分組以前的資料篩選使用where子句,分組以后的資料篩選使用having子句
-- 查詢年齡最大的學生的姓名(子查詢)
set @a=(select min(stu_birth) from tb_student);
select @a:=(select min(stu_birth) from tb_student);
select @a;
select stu_name from tb_student where stu_birth=@a;
-- 嵌套查詢:把一個select的結果作為另一個select的一部分來使用
-- 嵌套查詢通常也稱之為子查詢,在查詢陳述句中有兩個或多個select
select stu_name from tb_student
where stu_birth=(
select min(stu_birth) from tb_student
);
-- 查詢選了兩門以上的課程的學生姓名(子查詢/分組條件/集合運算)
select stu_name from tb_student
where stu_id in (
select stu_id from tb_record
group by stu_id having count(*)>2
);
-- 查詢學生的姓名、生日和所在學院名稱
select stu_name, stu_birth, col_name
from tb_student, tb_college
where tb_student.col_id=tb_college.col_id;
select stu_name, stu_birth, col_name
from tb_student t1 inner join tb_college t2
on t1.col_id=t2.col_id;
select stu_name, stu_birth, col_name
from tb_student natural join tb_college;
-- 查詢學生姓名、課程名稱以及成績(連接查詢/聯結查詢)
select t2.stu_id, stu_name, t3.cou_id, cou_name, score
from tb_record t1, tb_student t2, tb_course t3
where
t1.stu_id=t2.stu_id and
t1.cou_id=t3.cou_id and
score is not null;
select stu_name, cou_name, score
from tb_student t1 inner join tb_record t2
on t1.stu_id=t2.stu_id inner join tb_course t3
on t2.cou_id=t3.cou_id where score is not null;
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null;
-- 分頁查詢
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null
order by score desc limit 5;
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null
order by score desc limit 5 offset 5;
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null
order by score desc limit 5 offset 10; -- 表示 跳過前10個 取五個
select stu_name, cou_name, score
from tb_student natural join tb_record natural join tb_course
where score is not null
order by score desc limit 10,5; -- 表示 跳過前10個 取五個
-- alter table tb_record change column stu_id sid int unsigned not null;
-- alter table tb_record change column cou_id cid int unsigned not null;
-- 查詢選課學生的姓名和平均成績(子查詢和連接查詢)
select stu_name, avg_score
from
tb_student t1,
(
select stu_id, round(avg(score),1) as avg_score
from tb_record group by stu_id
) t2
where t1.stu_id=t2.stu_id;
-- 查詢學生的姓名和選課的數量
select stu_name, total
from
tb_student t1,
(
select stu_id, count(*) as total from tb_record
group by stu_id
) t2
where t1.stu_id=t2.stu_id;
-- 查詢每個學生的姓名和選課數量(左外連接和子查詢)
-- 內連接:查詢左右兩表滿足連接條件的資料,
-- 外連接
-- 左外連接:確保左表(現在join前面的表)中的所有記錄都能查出來,不滿足連接條件的補充null,
-- 右外連接:確保右表(現在join后面的表)中的所有記錄都能查出來,不滿足連接條件的補充null,
-- 全外連接:確保左表和右表中的所有記錄都能查出來,不滿足連接條件的補充null,
-- 左外連接
select stu_name, ifnull(total, 0) as total
from tb_student t1 left outer join (
select stu_id, count(*) as total from tb_record
group by stu_id
) t2 on t1.stu_id=t2.stu_id;
-- 洗掉tb_record表的外鍵約束
alter table tb_record drop foreign key fk_record_stu_id;
alter table tb_record drop foreign key fk_record_cou_id;
-- 給tb_record表加兩條記錄,學號5566在學生表沒有對應的記錄
insert into tb_record
values
(default, 5566, 1111, '2019-09-02', 80),
(default, 5566, 2222, '2019-09-02', 70);
-- 右外連接
select t1.stu_id, stu_name, t2.stu_id, total as total
from tb_student t1 right outer join (
select stu_id, count(*) as total from tb_record
group by stu_id
) t2 on t1.stu_id=t2.stu_id;
-- MySQL不支持全外連接
-- 可以通過左外連接與右外連接求并集運算得到全外連接的結果
select t1.stu_id, stu_name, t2.stu_id, total as total
from tb_student t1 left outer join (
select stu_id, count(*) as total from tb_record
group by stu_id
) t2 on t1.stu_id=t2.stu_id
union
select t1.stu_id, stu_name, t2.stu_id, total as total
from tb_student t1 right outer join (
select stu_id, count(*) as total from tb_record
group by stu_id
) t2 on t1.stu_id=t2.stu_id;
作業
drop database if exists hrs;
create database hrs default charset utf8mb4;
use hrs;
create table tb_dept
(
dno int not null comment '編號',
dname varchar(10) not null comment '名稱',
dloc varchar(20) not null comment '所在地',
primary key (dno)
);
insert into tb_dept values
(10, '會計部', '北京'),
(20, '研發部', '成都'),
(30, '銷售部', '重慶'),
(40, '運維部', '深圳');
create table tb_emp
(
eno int not null comment '員工編號',
ename varchar(20) not null comment '員工姓名',
job varchar(20) not null comment '員工職位',
mgr int comment '主管編號',
sal int not null comment '員工月薪',
comm int comment '每月補貼',
dno int comment '所在部門編號',
primary key (eno)
);
-- alter table tb_emp add constraint pk_emp_eno primary key (eno);
-- alter table tb_emp add constraint uk_emp_ename unique (ename);
-- alter table tb_emp add constraint fk_emp_mgr foreign key (mgr) references tb_emp (eno);
-- alter table tb_emp add constraint fk_emp_dno foreign key (dno) references tb_dept (dno);
insert into tb_emp values
(7800, '張三豐', '總裁', null, 9000, 1200, 20),
(2056, '喬峰', '分析師', 7800, 5000, 1500, 20),
(3088, '李莫愁', '設計師', 2056, 3500, 800, 20),
(3211, '張無忌', '程式員', 2056, 3200, null, 20),
(3233, '丘處機', '程式員', 2056, 3400, null, 20),
(3251, '張翠山', '程式員', 2056, 4000, null, 20),
(5566, '宋遠橋', '會計師', 7800, 4000, 1000, 10),
(5234, '郭靖', '出納', 5566, 2000, null, 10),
(3344, '黃蓉', '銷售主管', 7800, 3000, 800, 30),
(1359, '胡一刀', '銷售員', 3344, 1800, 200, 30),
(4466, '苗人鳳', '銷售員', 3344, 2500, null, 30),
(3244, '歐陽鋒', '程式員', 3088, 3200, null, 20),
(3577, '楊過', '會計', 5566, 2200, null, 10),
(3588, '朱九真', '會計', 5566, 2500, null, 10);
-- 查詢月薪最高的員工姓名和月薪
-- 查詢員工的姓名和年薪((月薪+補貼)*13)
-- 查詢有員工的部門的編號和人數
-- 查詢所有部門的名稱和人數
-- 查詢月薪最高的員工(Boss除外)的姓名和月薪
-- 查詢月薪超過平均月薪的員工的姓名和月薪
-- 查詢月薪超過其所在部門平均月薪的員工的姓名、部門編號和月薪
-- 查詢部門中月薪最高的人姓名、月薪和所在部門名稱
-- 查詢主管的姓名和職位
-- 查詢月薪排名4~6名的員工排名、姓名和月薪
\################################
use hrs;
-- 查詢月薪最高的員工姓名和月薪
select ename, sal from tb_emp where sal=(
select max(sal) from tb_emp
);
select ename, sal from tb_emp t1 where not exists (
select 'x' from tb_emp t2 where t2.sal>t1.sal
);
select ename, sal from tb_emp t1 where (
select count(*) from tb_emp t2 where t2.sal>t1.sal
)=0;
-- 查詢月薪前2名的員工的姓名和月薪
select ename, sal from tb_emp t1 where (
select count(*) from tb_emp t2 where t2.sal>t1.sal
)<2;
-- 查詢員工的姓名和年薪((月薪+補貼)*13)
select ename, (sal+ifnull(comm, 0))*13 as ann_sal from tb_emp;
-- 查詢有員工的部門的編號和人數
select dno, count(*) as total from tb_emp group by dno;
-- 查詢所有部門的名稱和人數
select dname, ifnull(total, 0) as total from tb_dept t1 left join
(select dno, count(*) as total from tb_emp group by dno) t2
on t1.dno=t2.dno;
-- 查詢月薪最高的員工(Boss除外)的姓名和月薪
select ename, sal from tb_emp where sal=(
select max(sal) from tb_emp where mgr is not null
);
-- 查詢月薪超過平均月薪的員工的姓名和月薪
select ename, sal from tb_emp where sal>(
select avg(sal) from tb_emp
);
-- 查詢月薪超過其所在部門平均月薪的員工的姓名、部門編號和月薪
select ename, t1.dno, sal from tb_emp t1 inner join
(select dno, avg(sal) as avg_sal from tb_emp group by dno) t2
on t1.dno=t2.dno and sal>avg_sal;
-- 查詢部門中月薪最高的人姓名、月薪和所在部門名稱
select ename, sal, dname
from
tb_emp t1, tb_dept t2,
(select dno, max(sal) as max_sal from tb_emp group by dno) t3
where t1.dno=t3.dno and sal=max_sal and t3.dno=t2.dno;
-- 查詢主管的姓名和職位
select ename, job from tb_emp where eno in (
select distinct mgr from tb_emp where mgr is not null
);
-- 建議:使用 exists / not exists 替代掉 distinct 和 in / not in 運算
select ename, job from tb_emp t1 where exists (
select 'x' from tb_emp t2 where t1.eno=t2.mgr
);
-- 查詢月薪排名4~6名的員工排名、姓名和月薪
select rank_num, ename, sal from
(
select @a:=@a+1 as rank_num, ename, sal
from tb_emp, (select @a:=0) t1
order by sal desc
) temp where rank_num between 4 and 6;
-- 視窗函式 ---> (離線)分析函式
-- row_number() 1 2 3 4 5 6 7 8 9 10 11
-- rank() 1 1 1 4 5 6 7 7 7 10 11
-- dense_rank() 1 1 2 3 4 4 4 5
-- 1. 查詢排名問題
-- 2. Top-N查詢
select rank_num, ename, sal
from (
select
dense_rank() over (order by sal desc) as rank_num,
ename,
sal
from tb_emp
) temp where rank_num between 4 and 6;
-- 查詢每個部門月薪前2名的員工姓名、月薪和部門編號
select ename, sal, dno from tb_emp t1 where (
select count(*) from tb_emp t2
where t1.dno=t2.dno and t2.sal>t1.sal
)<2 order by dno asc, sal desc;
-- 使用視窗函式完成上面的查詢
select ename, sal, dno
from (select
rank() over (partition by dno order by sal desc) as rank_num,
ename, sal, dno
from tb_emp) temp where rank_num<=2;
視窗函式
-- 視窗函式 ---> (離線)分析函式
-- row_number() 1 2 3 4 5 6 7 8 9 10 11
-- rank() 1 1 1 4 5 6 7 7 7 10 11
-- dense_rank() 1 1 2 3 4 4 4 5
-- 1. 查詢排名問題
-- 2. Top-N查詢
select rank_num, ename, sal
from (
select
dense_rank() over (order by sal desc) as rank_num,
ename,
sal
from tb_emp
) temp where rank_num between 4 and 6;
-- 查詢每個部門月薪前2名的員工姓名、月薪和部門編號
select ename, sal, dno from tb_emp t1 where (
select count(*) from tb_emp t2
where t1.dno=t2.dno and t2.sal>t1.sal
)<2 order by dno asc, sal desc;
-- 使用視窗函式完成上面的查詢
select ename, sal, dno
from (select
rank() over (partition by dno order by sal desc) as rank_num,
ename, sal, dno
from tb_emp) temp where rank_num<=2;
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/297910.html
標籤:其他
上一篇:Docker鏡像命令
