MySQL数据库
一、数据库的本质
1、数据库就是存储在硬盘上的格式化文件,通过一些手段可以很方便的这些文件进行增删改查
二、数据库的分类
1. 关系型数据库
① 特点
1、所有的数据都是由一张张表组成,这些表之间存在着关联关系
② 常见的数据库
MySQL、Oracle、SqlServer、DB2、PostgreSQL、SQLite
2. 非关系型数据库
① 特点
数据是以键值对的形式存放(name:'张三') (age:18)
② 常见的数据库
Redis、HBase、MangDB、Neo4j ....
三、 MySQL的介绍
1. 特点
1、MySQL是关系型数据库
2、MySQL一张表数据可以达到千万行数据量
3、MySQL支持标准SQL语言
2. 版本
社区版:免费
企业版:收费
集群版:免费/收费
#基础课程使用的是MySQL8.0社区版
四、SQL介绍
1. 概述
SQL(Structured Query Language)结构化查询语言,专门用于操作数据库的语言
2. DDL语言
操作数据库和表整体:
1)对数据整体进行增删改 (不涉及内容)
2)对表整体进行增删改(不涉及内容)
3. DML语言
对数据表的内容进行增删改: insert、update、delete
4. DQL语言
对数据表内容进行查询
5. DCL语言
用于权限控制,了解即可
6. 语法要求
1、SQL语句可以单行或多行书写,以分号结尾。
select * from students;
2、可使用空格和缩进来增强语句的可读性
3、MySQL数据库的SQL语句不区分大小写,关键字建议使用大写
例如:SELECT * FROM userSelect * from user;
4、可以使用/**/的方式完成注释 -- #
/**/:多行注释,在注释区域内可以随意换行
-- # :单行注释,写在语句开头,换行后注释截止。
注释快捷键:ctrl+/
五、进入MySQL终端
#进入:
mysql -uroot -p123456
#退出:
exit
#查询
select * from student;
六、DDL操作
1. 操作数据库
###############一、数据库操作#######################
-- 1、创建数据库
create database bigdata_db; #第一种写法,如果数据库存在则报错
create database if not exists bigdata_db;#第二种写法,如果数据库存在则不报错
-- 2、查看所有的数据库
show databases;
-- 3、删除数据库
drop database bigdata_db; #第一种写法
drop database if exists bigdata_db; #第二种写法,如果存在则删除
-- 4、选择要操作哪个数据库
use bigdata_db;
-- 5、查看当前正在使用哪个数据库
select database();
2. 操作表
###############二、表操作#######################
-- 1、创建表
/*
tinyint: - 128 到 127
smallint: 0 到 65535
mediumint:0 到 16777215
int : -2147483648 到 -2147483647
bigint :-9223372036854775808 到 2^63-1 (9223372036854775807)
*/
use bigdata_db;
create table if not exists student(
id int,
name varchar(20), -- '李涛、张三丰 、皇甫艳艳,澹台玄仲、古力那扎尔·拜合提亚尔'
sex varchar(2),
age tinyint
);
create table category(
cid varchar(20) primary key ,
cname varchar(100)
);
-- 2、查看所有的表
show tables ;
-- 3、查看表结构(查看该表有几个列,每列叫啥名字,每列啥类型)
desc student;
-- 4、删除表
drop table if exists student;
drop table if exists category;
-- 5、修改表结构(了解)
-- 5.1 给student表添加address列
alter table student add address varchar(64);
#如果你添加的列名和关键字冲突,则可以给列名上边加上一个飘号(反引号)
alter table student add `address` varchar(64);
-- 5.2 将student的address列名修改为addr
alter table student change address addr varchar(64);
-- 5.3 将student的addr列删除
alter table student drop addr;
-- 5.4 将student表名修改为stu
rename table student to stu;
七、DML操作
###############DML-三、表数据操作#######################
-- 1、给student表添加数据
-- insert into 表 (字段1,字段2,字段3...) values(值1,值2,值3...);
insert into student(id,name,sex,age) values (1,'刘备','男',43);
insert into student(id,name) values (2,'关羽');
insert into student values (3,'张飞','男',38);
insert into student values
(4,'小乔','女',18),
(5,'大乔','女',19),
(6,'赵云','男',21);
-- 2、修改student表数据
-- update 表名 set 字段名=值,字段名=值,...;
-- 将张飞的年龄修改为88
update student set age = 88;
update student set age = 88 where name = '张飞';
update student set age = 88 where name = '张飞';
-- 将曹操的性别修改为女,将年龄修改为99
update student set sex = '女' , age = 99 where id = 7;
-- 将每个人的年龄加上10岁
update student set age = age + 10;
-- 将曹操的id修改为77
update student set id = 77 where id = 7;
-- 将大乔和小巧的年龄减去50
update student set age = age - 50 where name = '小乔' or name = '大乔';
update student set sex = '男' where id >= 3 ;
-- 3、删除student表数据
-- delete from 表名 [where 条件];
delete from student;
-- 删除关羽
delete from student where name = '关羽';
-- 删除大乔,小巧,赵云
delete from student where name = '大乔' or name = '小乔' or name = '赵云';
delete from student where name in('大乔','小乔','赵云');
八、约束操作
1. 建表时添加约束
① 主键约束
###############DML-四、表的约束#######################
-- --------------------1、主键约束------------------
/*
1、主键约束:primary key
2、一个表只能有一个主键(一个主键可以包含一列,也可以包含多列)
3、主键列特点:非空 + 唯一
空值唯一的定义:null
*/
-- 1、创建person表,指定主键
create table if not exists person(
id int primary key , #指定该列是主键列
name varchar(20),
address varchar(64),
city varchar(20)
);
desc person;
insert into person values (1,'林冲','中国开封','开封市');
insert into person values (1,'智深','中国忻州','五台山'); #不能添加主键重复值
insert into person values (null,'智深','中国忻州','五台山'); #不能给主键列添加空值
-- 如果主键列是字符串类型,则注意空值问题
create table if not exists person2(
id varchar(20) primary key , #指定该列是主键列
name varchar(20),
address varchar(64),
city varchar(20)
);
insert into person2 values ('','智深','中国忻州','五台山'); #''不是null,可以添加
insert into person2 values ('','智深','中国忻州','五台山'); #不可以添加
insert into person2 values (null,'智深','中国忻州','五台山'); #不能给主键列添加空值
-- 在定义表之后单独指定主键列
create table if not exists person3(
id varchar(20) ,
name varchar(20),
address varchar(64),
city varchar(20),
primary key (id) -- 在这里指定id为主键列
);
-- 联合主键:多列组成一个主键,经纬度
/*
1、添加数据时,联合主键的列不能一模一样,只要有一列不同即可
1、添加数据时,联合主键的列,每一列都不能为空,否则报错
*/
create table if not exists person4(
id varchar(20) ,
name varchar(20) ,
address varchar(64),
city varchar(20),
primary key (id,name)
);
insert into person4 values ('1','智深','中国忻州','五台山');
insert into person4 values ('1','林冲','中国开封','开封市');
insert into person4 values ('2','智深','中国开封','开封市');
insert into person4 values (null,'智深','中国忻州','五台山'); #id列不能为空
-- --------------------1、主键约束-自动增长------------------
/*
1、自动增长关键字auto_increment只能和主键一起使用
2、自动增长的列一般是数字列,不能用于联合主键
3、自动增长默认是从1开始
4、如果你使用delete删除数据之后,下次主键依然从最大的值开始加1,不会再从从1开始
5、如果你想要主键从1开始重新增加,则可以使用truncate table 表名 来实现,
该命令内部是先删除表,再创建新表
*/
create table if not exists person5(
id int primary key auto_increment , #指定该列是主键列
name varchar(20),
address varchar(64),
city varchar(20)
);
insert into person5(name,address,city) values ('林冲','中国开封','开封市');
insert into person5 values (null,'林冲','中国开封','开封市'); #设置为null,自己增加
insert into person5 values (5,'林冲','中国开封','开封市'); #手动设置id值
insert into person5 values (null,'林冲','中国开封','开封市'); #下次从设置的id值+1开始
delete from person5;
-- 删除数据之后,可以通过以下该命令来修正自动增长的初始值
alter table person5 AUTO_INCREMENT 3;
insert into person5 values (null,'林冲','中国开封','开封市');
-- 如果你想让表的主键重新从1开始编号,你应该删除该表,再建新表,也就是使用命令:truncate table person5;
truncate table person5;
insert into person5 values (null,'林冲','中国开封','开封市');
set auto_increment_offset = 88;
insert into person5 values (null,'林冲','中国开封','开封市'); #从最高的加1
desc person5;
② 非空约束
-- --------------------2、非空约束------------------
/*
1、非空约束关键字:not null
2、如果某一列加了非空约束,该列的值不能为空
3、一张表可以多个列都添加非空约束
*/
create table if not exists person6(
id int primary key auto_increment , #指定该列是主键列
name varchar(20) not null,
address varchar(64),
city varchar(20)
);
insert into person6 values (null,'林冲','中国开封','开封市'); #可以
insert into person6 values (null,'','中国开封','开封市'); #可以
insert into person6 values (null,'null','中国开封','开封市'); #可以
insert into person6 values (null,null,'中国开封','开封市'); #不可以
insert into person6(address,city) values ('中国开封','开封市'); #不可以
desc person6;
③ 唯一约束
-- --------------------3、唯一约束------------------
/*
1、唯一约束添加之后,该列的值必须唯一
2、唯一约束关键字:unique
3、唯一约束的列可以添加多个null值,null非常特殊,null和任何值都不相同,和自己也不相同
*/
drop table person7;
create table if not exists person7(
id int primary key auto_increment , #指定该列是主键列
name varchar(20) not null,
address varchar(64) unique ,
city varchar(20)
);
insert into person7 values (null,'林冲','中国开封','开封市'); #可以
insert into person7 values (null,'林冲','中国开封','开封市'); #重复
insert into person7 values (null,'林冲',null,'开封市'); #可以
insert into person7 values (null,'林冲',null,'开封市'); #可以,null和任何值都不相同,甚至和自己都不相同
insert into person7 values (null,'林冲',null,'开封市'); #重复
select * from person7;
select * from person7 where 1=1;
select * from person7 where null=null; #没有任何结果
desc person7;
-- 联合唯一,多个字段只要有一列不同即可
create table if not exists person77(
id int primary key auto_increment , #指定该列是主键列
name varchar(20) not null,
address varchar(64) ,
city varchar(20),
unique (address,city)
);
insert into person77 values (null,'林冲','中国','开封市');
insert into person77 values (null,'林冲','中国','洛阳市');
insert into person77 values (null,'林冲','河南','开封市');
④ 默认值约束
-- --------------------4、默认值约束------------------
drop table person8;
create table if not exists person8(
id int primary key auto_increment , #指定该列是主键列
name varchar(20) not null,
address varchar(64) unique ,
city varchar(20) default '北京'
);
insert into person8 values (null,'林冲','中国开封',null); # city是null
insert into person8(id,name,address) values (null,'林冲','中国洛阳'); #city默认是北京
insert into person8 values (null,'林冲','中国杭州','杭州市'); #city指定为洛阳
insert into person8 values (null,'林冲','中国南京','南京市'); #city指定为洛阳
insert into person8 values (null,'林冲','中国武汉','武汉市'); #city指定为洛阳
⑤ 约束叠加
-- --------------------5、约束叠加------------------
drop table if exists person9;
create table if not exists person9(
id int primary key auto_increment , #指定该列是主键列
name varchar(20) not null,
address varchar(64) unique ,
city varchar(20) not null default '北京'
);
insert into person9 values (null,'林冲','中国武汉','武汉市');
insert into person9(id,name,address) values (null,'林冲','中国武汉1');
insert into person9(id,name,address) values (null,'林冲','中国武汉2');
insert into person9 values (null,'林冲','中国武汉',null);
desc person9;
desc person2;
2. 建表后添加约束(了解)
-- -----------------主键约束----------------------
-- 1、添加主键约束
-- ALTER TABLE 表名 ADD PRIMARY KEY(字段)
drop table student2;
CREATE TABLE student2(
sno int ,
sname VARCHAR(10),
sex VARCHAR(5),
age INT
);
alter table student2 add primary key (sno);
-- 1、给主键添加自动增长
# ALTER TABLE 表名 MODIFY 字段名 数据类型 AUTO_INCREMENT
alter table student2 modify sno int primary key auto_increment;
-- 2、删除删除主键约束
-- ALTER TABLE 表名 DROP PRIMARY KEY #因为主键是唯一的,不需要指明主键名
alter table student2 modify sno int ; #删除自动增长
alter table student2 drop primary key ; #删除主键
alter table student2 modify sno int null ; #删除非空
-- -----------------非空约束----------------------
-- 1、添加非空约束
-- ALTER TABLE student2 MODIFY sex VARCHAR(10) NOT NULL;
alter table student2 modify sex VARCHAR(10) not null;
-- 2、删除非空约束
alter table student2 MODIFY sex VARCHAR(10) null;
-- -----------------唯一约束----------------------
-- 1、添加唯一约束-方式1
-- age_uni是唯一约束的名字
alter table student2 add unique (sex); #如果没有给唯一约束起名字,则约束名字就是该列的列名
alter table student2 add constraint age_uni unique (age);
-- 1、添加唯一约束-方式2
alter table student2 modify sname varchar(10) unique ;
-- 2、删除唯一约束
drop index age_uni on student2;
ALTER TABLE student2 DROP INDEX sex;
-- -----------------默认约束----------------------
-- 1、添加默认约束
alter table student2 modify age int default 18;
-- 2、删除默认约束
alter table student2 modify age int;
九、DQL操作
简单查询
###############DQL-五、表的查询#######################
-- 1、准备查询的数据
# 创建商品表
drop table if exists bigdata_db.product;
CREATE TABLE bigdata_db.product
(
pid INT PRIMARY KEY,
pname VARCHAR(20),
price DOUBLE,
category_id VARCHAR(32)
);
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(1,'联想',5000,'c001');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(2,'海尔',3000,'c001');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(3,'雷神',5000,'c001');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(4,'杰克琼斯',800,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(5,'真维斯',200,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(6,'花花公子',440,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(7,'劲霸',2000,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(8,'海澜之家',1,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(9,'香奈儿',800,'c003');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(10,'相宜本草',200,'c003');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(11,'面霸',5,'c003');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(12,'好想你枣',56,'c004');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(13,'香飘飘奶茶',1,'c005');
-- 1、select基本查询
/*
格式:select [distinct]*| 列名,列名 from 表 [where 条件]
*/
-- 1.1 查询所有商品
select pid,pname,price,category_id from product;
select * from product;
-- 1.2 查询商品名和价格
select pname,price from product;
-- 1.2 查询所有商品加10元之后的价格
-- 给列起别名: 列表达式 as 别名 (as可以省略)
select pname, price+10 as new_price from product;
select pname, price+10 new_price from product;
条件查询
###############DQL-五、表的查询#######################
-- 1、select基本查询
/*
格式:select [distinct]*| 列名,列名 from 表 [where 条件]
*/
-- 1.1 查询所有商品
select pid,pname,price,category_id from product;
select * from product;
-- 1.2 查询商品名和价格
select pname,price from product;
-- 1.2 查询所有商品加10元之后的价格
-- 给列起别名: 列表达式 as 别名 (as可以省略)
select pname, price+10 as new_price from product;
select pname, price+10 new_price from product;
-- 2、条件查询
# 2.1 查询商品名称为“花花公子”的商品所有信息:
select * from product where pname = '花花公子';
# 2.2 查询价格为800商品
select * from product where price = 800;
# 2.3 查询价格不是800的所有商品
select * from product where price != 800;
select * from product where price <> 800;
select * from product where not price = 800;
select * from product where not price in (800) ;
# 2.4 查询价格是200 或者 800的商品信息
select * from product where price in (200,800) ;
select * from product where price = 200 or price = 800;
# 2.5 查询商品价格大于60元的所有商品信息
select * from product where price > 60;
# 2.6 查询商品价格小于等于800元的所有商品信息
select * from product where price <= 800;
# 2.7 查询商品价格在200到1000之间所有商品
select * from product where price between 200 and 1000;
select * from product where price >= 200 and price <= 1000;
# 2.8 查询以'香'字开头的商品
select * from product where pname like '香%';
# 2.8 查询第二个字为'想'的商品
-- 这里的下划线_ 用来匹配任意一个字符
select * from product where pname like '_想%';
# 2.9 查询四个字的商品信息
select * from product where pname like '____';
# 2.10 查询category_id 不为null的商品
select * from product where category_id is not null;
select * from product where not category_id is null;
# 2.10 查询category_id 为null的商品
select * from product where category_id is null;
select * from product where category_id = '';
select * from product where length(category_id) = 0;
select * from product where length(trim(category_id)) = 0;
select * from product where pname like '香%' and price > 200;
select * from product where substring(pname,5,1)= '茶';
排序查询
-- 3、排序查询
/*
格式:SELECT * FROM 表名 ORDER BY 排序字段 ASC|DESC;
ASC 升序 (默认) ascending
DESC 降序 descending
*/
-- 3.1 按照价格升序排序(默认是升序)
select * from product order by price asc;
select * from product order by price ;
-- 3.2 按照价格降序排序
select * from product order by price desc;
-- 3.3 使用字段表达式排序
select pid,pname,price+10,category_id from product order by price+10 desc ;
-- 3.4 排序使用多个字段
-- 先按照price进行升序排序,如果price相同,则按照pid升序排序
-- 前者是排序的主要条件,后者是排序的次要条件,只有前者相同,或者才能生效
/*
order by 颜值,能力,;
*/
select * from product order by price,pid;
select * from product order by price desc ,pid asc;
聚合查询
-- 4. 聚合查询
/*
count(* 或者 1或者 字段名):count不会统计null值
sum(字段名) : 对某一列求和
avg(字段名) : 对某一列求平均值,如果某列的值是null,则将这一行剔除出去,求剩余数值的平局值
max(字段名) : 对某一列求最大值
min(字段名) : 对某一列求最小值
*/
# 4.1、查询商品的总条数
select count(pid) from product; #统计pid列有13行不为null的值
select count(category_id) from product; #统计category_id列有12行不为null的值
select count(1) from product; #统计该表的行数 第一代写法
select count(*) from product; #统计该表的行数 第二代写法
# 4.2、查询价格大于200商品的总条数
select * from product where price > 200 ;
select count(*) from product where price > 200 ;
# 4.3、查询分类为'c001'的所有商品的价格总和
select sum(price) from product ;
select sum(price) from product where category_id = 'c001'
# 4.4、查询分类为'c002'所有商品的平均价格
select avg(price) from product;
select avg(price) from product where category_id = 'c002';
# 4.5、查询商品的最大价格和最小价格
select max(price) from product;
select min(price) from product;
select * from product where price = (select max(price) from product);
select max(price) max_price ,min(price) min_price from product;
select max(category_id) max_price ,min(category_id) min_price from product
分组查询
-- 5. 分组查询
/*
1、分组时,group by后边如果跟的是A字段,则select后边只能跟A字段和聚合函数
2、分组之后,如果还想进行条件筛选,必须用having,不能用where,where用在分组之间的条件筛选
*/
-- 5.1 查询每一种分类商品的个数
select category_id,count(*) from product group by category_id;
-- 5.2 查询每一种分类商品的个数,并筛选出商品个数大于3的信息
select category_id,count(*) from product group by category_id having count(*) > 3;
select category_id,count(*) as cnt from product group by category_id having cnt > 3;
-- ctrl + alt + l
select
category_id,
count(*) as cnt
from product
group by category_id
having cnt > 3;
-- 分组之后跟多个字段
create table test2(
id int,
name varchar(20),
province varchar(10),
city varchar(20),
sex varchar(2)
)
select province,count(*) from test2 group by province;
select city,count(*) from test2 group by city;
-- group by后边可以跟多个字段,只有province和city都一样才能分到同一组,字段顺序无所谓
select province,city,count(*) from test2 group by province, city;
select province,sex,count(*) from test2 group by province, sex;
分页查询
# 6、分页查询
/*
格式:
SELECT 字段1,字段2... FROM 表名 LIMIT M,N
M: 整数,表示从第几条索引开始,计算方式 (当前页-1)*每页显示条数
N: 整数,表示查询多少条数据
SELECT 字段1,字段2... FROM 表明 LIMIT 0,5
SELECT 字段1,字段2... FROM 表明 LIMIT 5,5
limit关键字:
limit 3:显示表的前三条
limit 5,5
*/
select * from product limit 5;
select * from product limit 0,5; #从第0行(第1行)开始显示,显示5行
select * from product limit 5,5; #从第5行(第6行)开始显示,显示5行
select * from product limit 10,5; #从第10行(第11行)开始显示,显示5行
select * from product limit 15,5; #从第15行(第16行)开始显示,显示5行
select * from product limit 10,3; #显示11,12,13行
-- 第一行
select * from product limit 0,120; #显示11,12,13行
select * from product limit 120,120; #显示11,12,13行
select * from product limit 240,120; #显示11,12,13行
去重问题
-
介绍
在MySQL中去重有两种方式:1、distinct关键字 2、使用group by关键字
-
操作
create table if not exists students(studentNo int primary key auto_increment, name varchar(20), sex varchar(2), hometown varchar(20), age int, class_id int, card varchar(20)); insert into students(name, sex, hometown, age, class_id, card) values ('王昭君', '女', '北京', 20, 1, '340322199001247654'), ('诸葛亮', '男', '上海', 18, 2, '340322199002242354'), ('张飞', '男', '南京', 24, 3, '340322199003247654'), ('白起', '男', '安徽', 22, 4, '340322199005247654'), ('大乔', '女', '天津', 19, 3, '340322199004247654'), ('孙尚香', '女', '河北', 18, 1, '340322199006247654'), ('百里玄策', '男', '山西', 20, 2, '340322199007247654'), ('小乔', '女', '河南', 15, 3, null), ('百里守约', '男', '湖南', 21, 1, ''), ('妲己', '女', '广东', 26, 2, '340322199607247654'), ('李白', '男', '北京', 30, 4, '340322199005267754'), ('孙膑', '男', '新疆', 26, 3, '340322199000297655'); select * from students order by sex; select class_id, sex, count(*) from students group by class_id, sex select * from students; drop table if exists student; CREATE TABLE if not exists student( id INT, NAME VARCHAR(20), chinese INT, english INT, math INT ); INSERT INTO student(id,NAME,chinese,english,math) VALUES(1,'张小明',89,78,90); INSERT INTO student(id,NAME,chinese,english,math) VALUES(2,'李进',67,53,95); INSERT INTO student(id,NAME,chinese,english,math) VALUES(3,'王五',75,78,77); INSERT INTO student(id,NAME,chinese,english,math) VALUES(4,'李一',88,98,92); INSERT INTO student(id,NAME,chinese,english,math) VALUES(5,'李来财',75,84,67); INSERT INTO student(id,NAME,chinese,english,math) VALUES(6,'张进宝',55,85,45); INSERT INTO student(id,NAME,chinese,english,math) VALUES(7,'黄蓉',75,65,30); INSERT INTO student(id,NAME,chinese,english,math) VALUES(7,'黄蓉',75,65,30); select * from student; -- 对某一列去重,以下两种方式等价 select distinct chinese from student; select chinese from student group by chinese; -- 对某一列去重,以下两种方式等价 select distinct province from test2; select province from test2 group by province; -- 对整行去重,以下几种方式等价 select distinct * from student; select * from student group by id,NAME,chinese,english,math; select * from student group by id,NAME,chinese,english,math; select id,NAME,chinese,english,math from student group by id,NAME,chinese,english,math; -- count去重------>先去重再统计 select count(distinct province) from test2;
十、多表查询
表与表之间的关系
概念
- 一对一关系
1、A表的每一行对应B表的每一行,同理B表的每一行也对应A表的每一行
2、由于该模型下两张表可以合成一张表,所以不需要过多关注
- 一对多关系
1、A表的每一行对应B表的多行,反之不可以,一对多一般描述的是包含关系
2、一对多关系是数据分析遇到最多的关系之一
- 多对多关系
1、A表的每一行对应B表的多行,反之B表的每一行都对应A的多行
2、多对多关系是数据分析最复杂的关系,这种关系表必须有中间表
部门表和员工表:
演员表 和 角色表:
表关系实现
- 一对多关系
######################表关系-一对多关系##############
# 1、创建分类表 -主表
drop table if exists category;
CREATE TABLE if not exists category(
cid VARCHAR(32) PRIMARY KEY,
cname VARCHAR(100)
);
# 2、创建商品表 -从表
-- 创建外键约束-方式1-在建表时直接指定
drop table if exists product;
CREATE TABLE if not exists product
(
pid INT PRIMARY KEY,
pname VARCHAR(20),
price DOUBLE,
category_id VARCHAR(32),
constraint fk_tb_product2 foreign key (category_id) references category(cid)
);
# 创建外键约束-方式2-在建表之后指定
-- 大小写转换 : Ctrl + Shift + u
/*
alter table 从表 add constraint 外键的名字
foreign key(从表外键列) references 主表(主表主键列);
*/
alter table product add constraint fk_tb_product
foreign key(category_id) references category(cid);
-- 验证有约束的数据操作
-- 添加数据
/*
1、先要添加主表数据,才能添加从表数据
*/
insert into category values ('c001','电器');
insert into category values ('c002','服装');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(1,'联想',5000,'c001');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(2,'海尔',3000,'c001');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(3,'雷神',5000,'c001');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(4,'杰克琼斯',800,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(5,'真维斯',200,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(6,'花花公子',440,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(7,'劲霸',2000,'c002');
INSERT INTO bigdata_db.product(pid,pname,price,category_id) VALUES(8,'海澜之家',1,'c002');
-- 删除数据
/*
1、必须先删除从表数据,才能删除主表数据
*/
delete from product where pname = '联想';
delete from product where pname = '雷神';
delete from product where pname = '海尔';
delete from product where category_id = 'c001';
delete from category where cid = 'c001';
-- 删除外键约束
-- alter table 从表 drop foreign key 外键约束名;
alter table product drop foreign key fk_tb_product2;
-- 结论
/*
对于外键约束而言,只是来约束你插入数据和删除数据的行为,对查询不会造成任何影响
*/
- 多对多关系
######################表关系-多对多关系##############
-- 1、创建左侧主表
drop table if exists actor;
create table actor(
actor_id int primary key ,
actor_name varchar(20)
);
-- 2、创建右侧主表
drop table if exists role;
create table role(
role_id int primary key ,
role_name varchar(20)
);
-- 3、创建中间从表
create table actor_role(
actor_id int,
role_id int
);
-- 4、创建左侧外键约束1
alter table actor_role add constraint fk_1 foreign key(actor_id)
references actor(actor_id);
-- 5、创建右侧外键约束2
alter table actor_role add constraint fk_2 foreign key(role_id)
references role(role_id);
-- 6、验证-数据的添加
/*
1、左侧主表和右侧主表的数据可以随便添加
*/
-- 添加左侧主表数据
insert into actor values
(1,'王宝强'),
(2,'杨幂'),
(3,'贾乃亮'),
(4,'迪丽热巴'),
(5,'胡歌');
-- 添加右侧主表数据
insert into role values
(1,'皇帝'),
(2,'太监'),
(3,'宫女'),
(4,'大臣'),
(5,'皇后');
-- 添加中间表
insert into actor_role values
(1,2),
(1,4),
(2,5),
(4,3),
(5,4);
多表join查询
查询方式
1、内连接查询
1.1 内连接求两张表的交集
2、外连接查询
2.1 左外连接
2.2 右外连接
内连接查询
#方式1
seelct * from A,B where 条件;
#方式2
seelct * from A inner jon B on 条件;
seelct * from A jon B on 条件; # 推荐
/*
1、内连接查询
1.1 内连接求两张表的交集
2、外连接查询
2.1 左外连接
2.2 右外连接
*/
-- 2.1 内连接查询
/*
#方式1
seelct * from A,B where 条件;
#方式2
seelct * from A inner jon B on 条件;
seelct * from A jon B on 条件;
*/
-- 方式1
alter table product drop foreign key fk_tb_product2;
select * from category,product; #笛卡尔集,将两张表进行相乘(表的行数=A表行数 * B表行数)
select * from category,product where cid = category_id;
-- 如果多张表中有同名的字段,则字段名前边必须加表名 : 表名.列名
select *
from actor,actor_role,role
where actor.actor_id = actor_role.actor_id and actor_role.role_id = role.role_id;
-- 可以给表起别名
select *
from actor as a,actor_role as ar,role as r
where a.actor_id = ar.actor_id and ar.role_id = r.role_id;
-- 方式2
select * from category inner join product; #笛卡尔集,将两张表进行相乘(表的行数=A表行数 * B表行数)
select * from category join product on cid = category_id;
-- 如果多张表中有同名的字段,则字段名前边必须加表名 : 表名.列名
select *
from actor,actor_role,role
where actor.actor_id = actor_role.actor_id and actor_role.role_id = role.role_id;
-- 可以给表起别名
select *
from actor as a,actor_role as ar,role as r
where a.actor_id = ar.actor_id and ar.role_id = r.role_id;
select
*
from actor a
join actor_role ar on a.actor_id = ar.actor_id
join role r on ar.role_id = r.role_id;
-- 手拉手join
# select
# *
# from A1
# join A2 on A1和A2关联条件
# join A3 on A2和A3关联条件
# join A4 on A3和A4关联条件
# join A5 on A4和A5关联条件;
#
#
# -- 小弟和大哥join
# select
# *
# from A1
# join A2 on A1和A2关联条件
# join A3 on A1和A3关联条件
# join A4 on A1和A4关联条件
# join A5 on A1和A5关联条件
-- 省表
create table province(
pid int primary key ,
name varchar(20)
);
-- 市表
create table city(
cid int primary key ,
name varchar(20),
pid int
);
-- 区表
create table county(
id int primary key ,
name varchar(20),
cid int
);
select
*
from province p
join city c on p.pid = c.pid
join county c2 on c.cid = c2.cid;
外连接查询
- 介绍
1、外连接查询
左外连接: left join
-- 以左表为主,一定会把左表的数据全部输出,右表有交集的数据就输出,没有交集的数据就输出null
右外连接: right join
-- 以右表为主,一定会把右表的数据全部输出,左表有交集的数据就输出,没有交集的数据就输出null
- 操作
-- 2.2 外连接查询
/*
1、外连接查询
左外连接: left join
-- 以左表为主,一定会把左表的数据全部输出,右表有交集的数据就输出,没有交集的数据就输出null
右外连接: right join
*/
-- 左外连接
select
*
from category
left join product p on category.cid = p.category_id;
/*
select
*
from A1
left join A2 on 条件1
left join A3 on 条件2
left join A4 on 条件3
left join A5 on 条件3
*/
-- 右外连接
select
*
from category
right join product p on category.cid = p.category_id;
-- 统计每种分类对应商品的个数
/*
电器 3
服装 5
化妆品 0
*/
select
cname,
count(pname) as total
from category c
left join product p on c.cid = p.category_id
group by cname
order by total desc;
自关联查询
- 介绍
1、有时,我们需要将一行表当成多张表来用,来实现该表的自关联,也就是表自己和自己关联
2、应用场景:
员工的上下级关系
行政区域的所属关系
商品分类的所属关系
- 操作
-- 3、自关联查询
use bigdata_db;
drop table employee;
create table employee(
eid int primary key comment '员工id', -- 员工id
ename varchar(20), -- 员工名
mgr_id int -- 员工上级领导id
);
insert into employee values (1,'刘备',13);
insert into employee values (2,'关羽',1);
insert into employee values (3,'张飞',1);
insert into employee values (4,'赵云',1);
insert into employee values (5,'曹操',13);
insert into employee values (6,'典韦',5);
insert into employee values (7,'徐晃',5);
insert into employee values (8,'郭嘉',5);
insert into employee values (9,'孙权',13);
insert into employee values (10,'周瑜',9);
insert into employee values (11,'鲁肃',9);
insert into employee values (12,'黄盖',9);
insert into employee values (13,'刘协',null);
-- 1、查询每个员工及其领导
/*
关羽 刘备
张飞 刘备
赵云 刘备
....
典韦 曹操
*/
select * from employee e join employee m ;
select * from employee e join employee m on e.mgr_id = m.eid;
select e.ename,m.ename from employee e join employee m on e.mgr_id = m.eid;
-- 通过以上sql发现,刘协由于是最大的boss,没有领导,如果要显示 : 刘协 null,则应该使用left join
/*
关羽 刘备
张飞 刘备
赵云 刘备
....
典韦 曹操
刘协 null
*/
select e.ename,m.ename from employee e left join employee m on e.mgr_id = m.eid;
/*
关羽 刘备 刘协
张飞 刘备 刘协
赵云 刘备 刘协
刘备 刘协 null
....
典韦 曹操 刘协
刘协 null null
*/
select e.ename,m1.ename,m2.ename
from employee e -- 员工
left join employee m1 on e.mgr_id = m1.eid -- 小领导
left join employee m2 on m1.mgr_id = m2.eid; -- 大领导
select
t1.name,
t2.name,
t3.name
from t_district t1 -- 县
left join t_district t2 on t1.pid = t2.id -- 市
left join t_district t3 on t2.pid = t3.id; -- 省
select count(*) from t_district;
-- 查看焦作市的下属行政区
select
t1.name,
t2.name,
t3.name
from t_district t1 -- 县
left join t_district t2 on t1.pid = t2.id -- 市
left join t_district t3 on t2.pid = t3.id -- 省
where t2.name = '焦作市';
select
t1.name,
t2.name,
t3.name
from t_district t1 -- 县
left join t_district t2 on t1.pid = t2.id -- 市
left join t_district t3 on t2.pid = t3.id -- 省
where t2.name = '深圳市';
-- 查询每个省级及自治区的所属行政区数量
select
t2.name,
count(*) as total
from t_district t1
right join
(
select
*
from t_district
where name like '%省' or name like '%自治区'
) t2
on t1.pid = t2.id
group by t2.name
order by total desc;
#自关联约束
一张表的一个列去约束另外一个列
alter table employee add constraint fk_e foreign key(mgr_id)
references employee(eid) ;
十一、子查询
- 介绍
如果一个条sql中出现了select嵌套,则查询就属于子查询
- 操作
######################子查询##############
-- 1、查询价格最高的商品详情信息
select max(price) from product;
select * from product where price = 5000;
-- 将查询的结果当做一个值
select * from product where price = (select max(price) from product);
-- 2、查询价格最高的商品详情信息
-- 将查询的结果有多个值
-- 查询电器和服装的商品信息详情
-- 方式1- 多表查询
select
*
from category c
left join product p on c.cid = p.category_id
where cname in ('电器','服装');
-- 方式2- 子查询
select cid from category where cname in ('电器','服装');
select * from product where category_id in('c001','c002');
-- 子查询的结果当做多个值
select * from product where category_id in(select cid from category where cname in ('电器','服装'));
-- 子查询的结果当做一张表
select
*
from
(select * from category where cname in ('电器','服装') ) t1
join
(select * from product) t2
on t1.cid = t2.category_id;
/*
select
*
from (select * from A1 where 条件)
left join (select * from A2 where 条件) on 条件
left join (select * from A3 where 条件) on 条件
left join (select * from A4 where 条件) on 条件;
*/
-- 查询价格>1000的服装商品详情信息
-- 挑选服装分类信息
select * from category where cname = '服装';
-- 挑选价格>1000的分类信息
select * from product where price >= 1000;
select
*
from (select * from category where cname = '服装') t1
join
(select * from product where price >= 1000) t2
on t1.cid = t2.category_id;
-- 查找比服装商品平均价格高的其他商品详情
-- 1、先求服装商品的平均价格
select avg(price) from category join product p on category.cid = p.category_id where cname = '服装';
-- 2、判断其他商品的价格是否大于服装商品的平均价格
select * from product where price > (服装商品的平均价格);
-- 获取其他商品
select
*
from product
where category_id != (select cid from category where cname = '服装')
and price > (select avg(price) from category join product p on category.cid = p.category_id where cname = '服装'
);
-- 查询商品价格是在最低和最高之间
select * from product
where price > (select min(price) from product) and price < (select max(price) from product);
十二、with语句
- 介绍
#----------原始写法------------
select
*
from (select * from A where 条件1) t1
join
(select * from B where 条件2) t2
on 条件3;
#---------------简化写法-------------------
with t1 as(
select * from A where 条件1
),
t2 as (
select * from B where 条件2
)
select * from t1 join t2 on 条件3;
######################嵌套包含简化#########################
#----------原始写法------------
select
*
from
(select * from (select * from A)tt)t;
#---------------简化写法-------------------
with tt as (
select * from A
),
t as (
select * from tt
)
select * from t;
- 操作
-- 学生表 Student
create table Student(SId varchar(10),Sname varchar(10),Sage datetime,Ssex varchar(10));
insert into Student values('01' , '赵雷' , '1990-01-01' , '男');
insert into Student values('02' , '钱电' , '1990-12-21' , '男');
insert into Student values('03' , '孙风' , '1990-05-20' , '男');
insert into Student values('04' , '李云' , '1990-08-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吴兰' , '1992-03-01' , '女');
insert into Student values('07' , '郑竹' , '1989-07-01' , '女');
insert into Student values('09' , '张三' , '2017-12-20' , '女');
insert into Student values('10' , '李四' , '2017-12-25' , '女');
insert into Student values('11' , '李四' , '2017-12-30' , '女');
insert into Student values('12' , '赵六' , '2017-01-01' , '女');
insert into Student values('13' , '孙七' , '2018-01-01' , '女');
-- 科目表 Course
create table Course(CId varchar(10),Cname nvarchar(10),TId varchar(10))
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');
-- 教师表 Teacher
create table Teacher(TId varchar(10),Tname varchar(10))
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
-- 成绩表 SC
create table SC(SId varchar(10),CId varchar(10),score decimal(18,1))
insert into SC values('01' , '01' , 80);
insert into SC values('01' , '02' , 90);
insert into SC values('01' , '03' , 99);
insert into SC values('02' , '01' , 70);
insert into SC values('02' , '02' , 60);
insert into SC values('02' , '03' , 80);
insert into SC values('03' , '01' , 80);
insert into SC values('03' , '02' , 80);
insert into SC values('03' , '03' , 80);
insert into SC values('04' , '01' , 50);
insert into SC values('04' , '02' , 30);
insert into SC values('04' , '03' , 20);
insert into SC values('05' , '01' , 76);
insert into SC values('05' , '02' , 87);
insert into SC values('06' , '01' , 31);
insert into SC values('06' , '03' , 34);
insert into SC values('07' , '02' , 89);
insert into SC values('07' , '03' , 98);
-- 1.查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数
-- 左表留下01成绩
select * from Student s join SC c on s.SId = c.SId and CId = '01';
-- 左表留下02成绩
select * from Student s join SC c on s.SId = c.SId and CId = '02';
-- 左右两个表关联
select
*
from (select s.SId,c.CId,c.score from Student s join SC c on s.SId = c.SId and CId = '01') t1
join
(select s.SId,c.CId,c.score from Student s join SC c on s.SId = c.SId and CId = '02') t2
on t1.SId = t2.SId
where t1.score > t2.score;
-- 简化写法
with t1 as(
select s.SId,c.CId,c.score from Student s join SC c on s.SId = c.SId and CId = '01'
),
t2 as (
select s.SId,c.CId,c.score from Student s join SC c on s.SId = c.SId and CId = '02'
)
select
t1.SId ,
s.Sname,
t1.score as t1_score,
t2.score as t2_score
from t1
join t2 on t1.SId = t2.SId
join Student s on s.SId = t2.SId
where t1.score > t2.score;
-- 2.查询学过「张三」老师授课的同学的信息
-- 3.查询没有学全所有课程的同学的信息
select
s.SId,
s.Sname
from Student as s
left join SC as sc on s.SId = sc.SId
left join Course as c on sc.CId = c.CId
group by s.SId,s.Sname
having count(s.SId) < (select count(*) from Course);
-- 4.查询各科成绩最高分、最低分和平均分,及格率:
-- 以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率
select
c.CId,
Cname,
max(score) as max_score,
min(score) as min_score,
avg(score) as avg_score,
concat(round(sum(if(score >= 60,1,0)) / count(*) * 100,2),'%') as pass_rate
from Course as c
join SC as sc on c.CId = sc.CId
group by c.CId,Cname;
十三、MySQL的函数
字符串函数
##################MySQL的函数########################
-- 数据准备
drop table emp;
create table emp(
emp_id int primary key auto_increment comment '编号',
emp_name char(20) not null default '' comment '姓名',
salary decimal(10,2) not null default 0 comment '工资',
department char(20) not null default '' comment '部门'
);
insert into emp(emp_name,salary,department)
values('张晶晶',5000,'财务部'),('王飞飞',5800,'财务部'),('赵刚',6200,'财务部'),('刘小贝',5700,'人事部'),
('王大鹏',6700,'人事部'),('张小斐',5200,'人事部'),('刘云云',7500,'销售部'),('刘云鹏',7200,'销售部'),
('刘云鹏',7800,'销售部');
-- 1、求绝对值:abs()函数
select abs(-5);
select abs(5);
-- 计算 张晶晶和王飞飞 薪资差多少
-- 查找张晶晶薪资
select salary from emp where emp_name = '张晶晶';
-- 查找王飞飞薪资
select salary from emp where emp_name = '王飞飞';
-- 方式1
select
abs(
(select salary from emp where emp_name = '张晶晶') - (select salary from emp where emp_name = '王飞飞')
);
-- 方式2
-- select abs(张晶晶薪资-王飞飞薪资) from 张晶晶薪资表 join 王飞飞薪资表
select abs(t1.salary-t2.salary) as diff_salary
from (select salary from emp where emp_name = '张晶晶')t1
join (select salary from emp where emp_name = '王飞飞')t2;
-- 2、ceil 和 floor
-- ceil 向上取整
-- floor 向下取整
select ceil(12.11); #向上找一个最近的整数
select ceil(12.00); #12
select floor(12.99); #向下找一个最近的整数,把零头抹掉
-- 3、greatest 返回列表最大值,可以求一行多列的最大值
select greatest(12,123,99,34,45);
/*
1,张小明,89,78,90
2,李进,67,53,95
3,王五,75,78,77
*/
select name,greatest(chinese,english,math) as max_score from student;
-- 4、least 返回列表最小值,可以求一行多列的最小值
select least(12,123,99,34,45);
/*
1,张小明,89,78,90
2,李进,67,53,95
3,王五,75,78,77
*/
select name,greatest(chinese,english,math) as min_score from student;
-- 5、pow 求几次方
select pow(2,3); #求2的3次方
select pow(100,100); #求100的100次方
-- 6、rand 产生随机数
-- rand产生0-1之间的随机数,包含0,不包含1
select rand();
-- rand产生1-100之间的随机数
-- [0 - 99] + 1 ---> [1,100]
select floor(rand() * 100 + 1); # 1 - 100
select ceil(rand() * 100); # 0 - 100
-- [0 - 99] + 1 ---> [500,1000]
select floor(rand() * 100 + 1);
select floor(rand() * 501 + 500);
-- 求n到m之间的随机公式
-- floor(rand() * (m - n + 1) + n)
select floor(rand() * (1000 - 500 + 1) + 500);
select floor(rand() * 501 + 500);
select floor(rand() * (100 - 1 + 1) + 1);
select floor(rand() * 100 + 1);
-- 7、round 四舍五入
select round(3.499); #4舍
select round(3.511); #5入
#将一个数+0.5,向下取整就可以实现四舍五入
select floor(4875.5001 + 0.5);
select floor(4875.4001 + 0.5);
-- 四舍五入的同时保留n位小数
select round(3.499,2);
select round(3.484,2);
select round(3.485,2);
-- 8、字符串拼接:concat,concat_ws
select concat('hello','world');
select concat(emp_name,'_',department) from emp;
select concat('河北省','保定市','竞秀区','中山路38号');
-- concat_ws 在拼接式可以指定固定的分隔符
-- 2020-12-23
select concat_ws('-','2020','12','23');
-- 2020-12-23 11:34:56
select concat(concat_ws('-','2020','12','23'),' ',concat_ws(':','11','34','56'));
-- 9、去除空格
-- ltrim 去除左边空格
-- rtrim 去除右边空格
-- trim 去除两边空格
select ' hello ';
select ltrim(' hello ') as x;
select rtrim(' hello ') as x;
select trim(' hello ') as x;
select concat('llll',(' hello '),'rrrrr')as x;
select concat('llll',ltrim(' hello '),'rrrrr')as x;
select concat('llll',rtrim(' hello '),'rrrrr')as x;
select concat('llll',trim(' hello '),'rrrrr')as x;
-- 10、替换
select replace('你是个sb!','sb','**');
-- 将字符串中的sb全部替换为**
select replace('你是个sb,他也是个sb!','sb','**'); #全部替换
-- 11、字符串翻转
select reverse('13812345678');
-- 12、大小写转换
-- upper 将小写转大写
-- lower 将大写转小写
select upper('KDJKeieieeeKJJ');
select lower('KDJKeieieeeKJJ');
-- 13、字符串截取 substring ,substr
-- substring ,substr 等价
select substring('helloworld',2); -- 从第二个字符开始截取到最后
select substr('helloworld',2); -- 从第二个字符开始截取到最后
select substring('helloworld',1); -- 从第1个字符开始截取到最后
select substring('helloworld',2,4); -- 从第2个字符开始截取,截取4个长度
select substring('2020-12-23 11:34:56',6,5); -- 从第6个字符开始截取,截取5个长度
select substring('2020-12-23 11:34:56',-5,2); -- 从倒数第5个开始,截取2个长度
-- 统计每一个姓氏人数-方式1
with t as (
select substring(name,1,1) as first_name from student
)
select first_name,count(*) as cnt from t group by first_name order by cnt desc;
-- 统计每一个姓氏人数-方式2
select
substring(name,1,1) as first_name,
count(*) as cnt
from student
group by substring(name,1,1)
order by cnt desc;
with t as (
select
length(name) / 3 as info,
concat(count(*),'人') as cnt
from student
group by length(name) / 3
)
select concat(floor(info),'个字人数') as info,cnt from t;
数学函数
-- 1、求绝对值:abs()函数
select abs(-5);
select abs(5);
-- 计算 张晶晶和王飞飞 薪资差多少
-- 查找张晶晶薪资
select salary from emp where emp_name = '张晶晶';
-- 查找王飞飞薪资
select salary from emp where emp_name = '王飞飞';
-- 方式1
select
abs(
(select salary from emp where emp_name = '张晶晶') - (select salary from emp where emp_name = '王飞飞')
);
-- 方式2
-- select abs(张晶晶薪资-王飞飞薪资) from 张晶晶薪资表 join 王飞飞薪资表
select abs(t1.salary-t2.salary) as diff_salary
from (select salary from emp where emp_name = '张晶晶')t1
join (select salary from emp where emp_name = '王飞飞')t2;
-- 2、ceil 和 floor
-- ceil 向上取整
-- floor 向下取整
select ceil(12.11); #向上找一个最近的整数
select ceil(12.00); #12
select floor(12.99); #向下找一个最近的整数,把零头抹掉
-- 3、greatest 返回列表最大值,可以求一行多列的最大值
select greatest(12,123,99,34,45);
/*
1,张小明,89,78,90
2,李进,67,53,95
3,王五,75,78,77
*/
select name,greatest(chinese,english,math) as max_score from student;
-- 4、least 返回列表最小值,可以求一行多列的最小值
select least(12,123,99,34,45);
/*
1,张小明,89,78,90
2,李进,67,53,95
3,王五,75,78,77
*/
select name,greatest(chinese,english,math) as min_score from student;
-- 5、pow 求几次方
select pow(2,3); #求2的3次方
select pow(100,100); #求100的100次方
-- 6、rand 产生随机数
-- rand产生0-1之间的随机数,包含0,不包含1
select rand();
-- rand产生1-100之间的随机数
-- [0 - 99] + 1 ---> [1,100]
select floor(rand() * 100 + 1); # 1 - 100
select ceil(rand() * 100); # 0 - 100
-- [0 - 99] + 1 ---> [500,1000]
select floor(rand() * 100 + 1);
select floor(rand() * 501 + 500);
-- 求n到m之间的随机公式
-- floor(rand() * (m - n + 1) + n)
select floor(rand() * (1000 - 500 + 1) + 500);
select floor(rand() * 501 + 500);
select floor(rand() * (100 - 1 + 1) + 1);
select floor(rand() * 100 + 1);
-- 7、round 四舍五入
select round(3.499); #4舍
select round(3.511); #5入
#将一个数+0.5,向下取整就可以实现四舍五入
select floor(4875.5001 + 0.5);
select floor(4875.4001 + 0.5);
-- 四舍五入的同时保留n位小数
select round(3.499,2);
select round(3.484,2);
select round(3.485,2);
日期函数
# -----------------------日期函数----------------------------
-- 1、获取从1970年到此时此刻的秒值
select unix_timestamp();
-- 2、将指定的时间字符串转为秒值
select unix_timestamp('2023-12-27 14:42:56');
-- 3、统计你来到这个世界多少天
select (unix_timestamp() - unix_timestamp('2001-11-11 11:58:32')) / 3600 / 24;
-- 4、将秒值转为指定的格式
-- (1598079966,'%Y-%m-%d %H:%i:%s'); -> 2020-08-22 15-06-06
SELECT FROM_UNIXTIME(1598079966,'%Y-%m-%d %H:%i:%s');
-- 5、将2023-12-27 14:42:56 转为 202年12月27日 14时42分56秒
-- 2023-12-27 14:42:56 ----> 2023年12月27日 14时42分56秒
-- 2023-12-27 14:42:56 ----> 2023/12/27 14:42:56
SELECT FROM_UNIXTIME(unix_timestamp('2023-12-27 14:42:56'),'%Y年%m月%d日 %H时%i分%s秒');
-- 6、获取当前的年月日
select current_date(); -- 获取年月日: 2023-12-27
select current_time(); -- 获取时分秒:14:55:03
select current_timestamp(); -- 获取年月日时分秒: 2023-12-27 14:55:31
select now(); -- 获取年月日时分秒: 2023-12-27 14:55:31
-- 7、从日期字符串中提取年月日
select date('2023-12-27 14:42:56'); -- 2023-12-27 得到的是日期类型
select substring('2023-12-27 14:42:56',1,10); -- 2023-12-27 得到的是字符串
-- 8、计算日期之间相差的天数
select abs(datediff('2008-08-08',current_date()));
-- 最近7入购物的统计,最近30天,最近60天
select abs(datediff('2023-12-07',current_date())) < 30;
-- 9、计算小时之间的差值
select timediff('14:42:56','15:15:23'); -- 00:32:27
-- 10、日期格式化
SELECT DATE_FORMAT('2011-11-11 11:11:11','%Y-%m-%d %r');
SELECT DATE_FORMAT('2011-11-11 11:11:11','%Y/%m/%d %H:%i:%s');
-- 2011-1-1 1:1:1 转为 2011-01-01 01:01:01
SELECT DATE_FORMAT('2011-1-1 1:1:1','%Y-%m-%d %H:%i:%s');
-- 2020-4-12 21:20 ---> 2020-04-12 21:20:00
SELECT DATE_FORMAT('2020-4-12 21:20','%Y-%m-%d %H:%i:%s');
SELECT STR_TO_DATE('August 10 2017', '%M %d %Y');
-- 11 、将日期向前后推移
-- 时间向前推2天
select date_sub('2023-12-27 14:42:56',interval 2 day) ;
select date_add('2023-12-27 14:42:56',interval -2 day);
-- 时间向后推2天
select date_sub('2023-12-27 14:42:56',interval -2 day) ;
select date_add('2023-12-27 14:42:56',interval 2 day) ;
-- 时间向后推3年
select date_sub('2023-12-27 14:42:56',interval -3 year) ;
select date_add('2023-12-27 14:42:56',interval 3 year) ;
-- 时间向后推1周
select date_sub('2023-12-27 14:42:56',interval -1 week) ;
select date_add('2023-12-27 14:42:56',interval 1 week) ;
-- 统计任何一个年份的2月有几天,将时间定为该年的3月1日,然后时间向前推一天,就是2月的最后一天
select date_sub('2023-03-01',interval 1 day) ;
-- 12、从日期中提取指定的值
-- 从日期中提取分钟
select extract(minute from '2023-12-27 14:42:56');
-- 从日期中提取小时
select extract(hour from '2023-12-27 14:42:56');
-- 从日期中提取年
select extract(year from '2023-12-27 14:42:56');
-- 从日期中提取季度
select extract(quarter from '2023-12-27 14:42:56');
-- 从日期中提取周(今年的第几周)
select extract(week from '2023-12-27 14:42:56');
-- 从日期中提取周几
select YEAR('2023-12-27 14:42:56');
select MONTH('2023-12-27 14:42:56');
select DAY('2023-12-27 14:42:56');
select HOUR('2023-12-27 14:42:56');
select MINUTE('2023-12-27 14:42:56');
select SECOND('2023-12-27 14:42:56');
-- 1:周日 2:周一 3:周二 4:周三 5:周四 6:周五 7:周六
select DAYOFWEEK('2023-12-27 14:42:56');
-- 获取季度
select QUARTER('2023-12-27 14:42:56');
select min(date_code),max(date_code) from t_date;
-- 13、获取今天是周几
-- 1:周日 2:周一 3:周二 4:周三 5:周四 6:周五 7:周六
select dayofweek(current_date());
逻辑处理函数
# -----------------------逻辑处理函数----------------------------
-- 1、if语句
select if(2 > 1 , '大于','小于'); -- 条件成立,则取第一个值,否则取第二值
select if(2 < 1 , '大于','小于');
select *,'及格' as status from SC;
select *,'不及格' as status from SC;
-- 给表添加一列,标记是及格还是不及格
select *,if(score >= 60,'及格','不及格') as status from SC;
-- 统计及格和不及格人数
select sum(if(score >= 60,1,0)), sum(if(score >= 60,0,1)) from SC;
-- 2、ifnull
-- select ifnull(值1,值2) :如果值1为null,则返回值2,否则还是返回值1
-- 该函数用来处理null值问题
select ifnull(1,2);
select * from emp;
select 800 * 12 + if();
select ename, 12 * sal + ifnull(comm,0) as year_sal from emp;
-- 3、case when 语句
-- 格式1
/*
case
when 条件1 then '值1'
when 条件2 then '值2'
when 条件3 then '值3'
else
'值' -- else可以没有
end
*/
select
*,
case
when score >= 90 then '优秀'
when score >= 80 then '良好'
when score >= 60 then '及格'
else
'不及格'
end as status
from SC;
select
*,
case
when orders.pay_type = 1 then '微信支付'
when orders.pay_type = 2 then '支付宝支付'
when orders.pay_type = 3 then '银行卡支付'
else
'其他'
end as status
from orders;
-- 格式2
/*
case 字段
when 值1 then '信息1'
when 值2 then '信息2'
when 值3 then '信息3'
else
'信息4' -- else可以没有
end
*/
create table orders(
oid int primary key, -- 订单id
price double, -- 订单价格
pay_type int -- 支付类型(1:微信支付 2:支付宝支付 3:银行卡支付 4:其他)
);
insert into orders values(1,1200,1);
insert into orders values(2,1000,2);
insert into orders values(3,200,3);
insert into orders values(4,3000,1);
insert into orders values(5,1500,2);
select
*,
case orders.pay_type
when 1 then '微信支付'
when 2 then '支付宝支付'
when 3 then '银行卡支付'
else
'其他'
end as status
from orders;