主頁 > 資料庫 > 半天學會MySQL

半天學會MySQL

2021-09-06 09:24:19 資料庫

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命令的幫助,

    ?show

    2.查看有哪些幫助內容

    ?contents

    3.獲取函式的幫助

    ?functions

    4.獲取資料型別的幫助

    ?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鏡像命令

下一篇:粉絲靠這篇《兩萬字MySql陳述句總結》換到了女神微信,你不了解一下嗎??建議收藏

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more