Python学习日志
RBHGO的主页欢迎关注
温馨提示:创作不易,如有转载,注明出处,感谢配合~
目录
Python学习日志16课 - 数据库SQL查询
SQL —> DQL —> select
这里只写了select ,不代表只有select 。在用SQL语句查询时,SQL语句它是多变的,同一条题目要求会有很多不同的写法,所有只有写的足够多,不管遇到什么样的查询,我们都能有方法写出来。本文以三个难度依次递增的查询题目主要分享MySQL但不仅限于MySQL的SQL查询。
就像Python学习日志15中提到的,我们首先要在数据库中建立多表,且表与表之间要具有联系。所以现在我们就来在以shool这个数据库为例,建立多个表。
DQL (数据查询语言)
-
MySQL 中支持多种类型的运算符,包括:算术运算符(+ 、- 、* 、/ 、% )、比较运算符(= 、<> 、<=> 、< 、<= 、> 、>= 、BETWEEN...AND.. .、IN 、IS NULL 、IS NOT NULL 、LIKE 、RLIKE 、REGEXP )、逻辑运算符(NOT 、AND 、OR 、XOR )和位运算符(& 、| 、^ 、~ 、>> 、<< ),我们可以在 DQL 中使用这些运算符处理数据。 -
在查询数据时,可以在SELECT 语句及其子句(如WHERE 子句、ORDER BY 子句、HAVING 子句等)中使用函数,这些函数包括字符串函数、数值函数、时间日期函数、流程函数等。 函数不会用没关系,上面那一篇分享中也提到过,通过? +函数名 (?function查看所有函数)可以得到函数的使用方法。 这里以ROUND函数为例子我们在命令提示符(Workbench中不行)中mysql -u root -p 进入MySQL(前提是您装了MySQL),? round ,我们就会得到反馈大致如下: round() —> 四舍五入,可以设定位数
- round(1.298,2) -> 1.30
- round(1.298,0) -> 1
- round(211.298,-2) -> 200
温馨提示: SQL语句在不同数据库间相通,但会有些许不同,意思就是每一种数据库都会有自己的”方言“,我这里前提是MySQL。
常用字符串函数
函数 | 功能 |
---|
CONCAT | 将多个字符串连接成一个字符串 | FORMAT | 将数值格式化成字符串并指定保留几位小数 | FROM_BASE64 / TO_BASE64 | BASE64解码/编码 | BIN / OCT / HEX | 将数值转换成二进制/八进制/十六进制字符串 | LOCATE | 在字符串中查找一个子串的位置 | LEFT / RIGHT | 返回一个字符串左边/右边指定长度的字符 | LENGTH / CHAR_LENGTH | 返回字符串的长度以字节/字符为单位 | LOWER / UPPER | 返回字符串的小写/大写形式 | LPAD / RPAD | 如果字符串的长度不足,在字符串左边/右边填充指定的字符 | LTRIM / RTRIM | 去掉字符串前面/后面的空格 | ORD / CHAR | 返回字符对应的编码/返回编码对应的字符 | STRCMP | 比较字符串,返回-1、0、1分别表示小于、等于、大于 | SUBSTRING | 返回字符串指定范围的子串 |
常用数值函数
函数 | 功能 |
---|
ABS | 返回一个数的绝度值 | CEILING / FLOOR | 返回一个数上取整/下取整的结果 | CONV | 将一个数从一种进制转换成另一种进制 | CRC32 | 计算循环冗余校验码 | EXP / LOG / LOG2 / LOG10 | 计算指数/对数 | POW | 求幂 | RAND | 返回[0,1)范围的随机数 | ROUND | 返回一个数四舍五入后的结果 | SQRT | 返回一个数的平方根 | TRUNCATE | 截断一个数到指定的精度 | SIN / COS / TAN / COT / ASIN / ACOS / ATAN | 三角函数 | SUM | 返回条件下的数值的和 | AVG | 返回条件下的数值的平均数 | MAX / MIN | 最大值 / 最小值 |
常用时间日期函数
函数 | 功能 |
---|
CURDATE / CURTIME / NOW | 获取当前日期/时间/日期和时间 | ADDDATE / SUBDATE | 将两个日期表达式相加/相减并返回结果 | DATE / TIME | 从字符串中获取日期/时间 | YEAR / MONTH / DAY | 从日期中获取年/月/日 | HOUR / MINUTE / SECOND | 从时间中获取时/分/秒 | DATEDIFF / TIMEDIFF | 返回两个时间日期表达式相差多少天/小时 | MAKEDATE / MAKETIME | 制造一个日期/时间 |
常用流程函数
函数 | 功能 |
---|
IF | 根据条件是否成立返回不同的值 | IFNULL | 如果为NULL则返回指定的值否则就返回本身 | NULLIF | 两个表达式相等就返回NULL否则返回第一个表达式的值 |
其他常用函数
函数 | 功能 |
---|
MD5 / SHA1 / SHA2 | 返回字符串对应的哈希摘要 | CHARSET / COLLATION | 返回字符集/校对规则 | USER / CURRENT_USER | 返回当前用户 | DATABASE | 返回当前数据库名 | VERSION | 返回当前数据库版本 | FOUND_ROWS / ROW_COUNT | 返回查询到的行数/受影响的行数 | LAST_INSERT_ID | 返回最后一个自增主键的值 | UUID / UUID_SHORT | 返回全局唯一标识符 |
正式开始
如果您看到这里并且对此感兴趣,那么请一条一条的和我写下来,我在题目上基本都有会提示,并且会 一 一 介绍碰到的知识。如果您能看懂每一条语句,并且您都可以独立写下来,那么您对SQL查询语句就已经基本掌握。后续如果能继续练习,那么基本上您以后遇到的SQL查询,都可以用以下的方法做出来。
建库建表一
第一个数据库是学校库,有学生表、老师表、课程表、学院表、选课记录表。表与表之间都存在着关系,分别是1对1、一对多和多对多,我们建表之间应该对他们的关系应该做到心里有数,不过增删改不是这篇分享的重点。
drop database if exists `school`;
create database `school` default character set utf8mb4;
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 '选课记录表';
use school;
insert into `tb_college`
(`col_name`, `col_intro`)
values
('Python学院', 'Python 是由 Guido van Rossum 在八十年代末和九十年代初,在荷兰国家数学和计算机科学研究所设计出来的。Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。'),
('Java学院', 'Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。Java 可运行于多个平台,如 Windows, Mac OS 及其他多种 UNIX 版本的系统。后来 Sun 公司被 Oracle (甲骨文)公司收购,Java 也随之成为 Oracle 公司的产品。Java 语言是简单的、Java 语言是面向对象的、Java语言是分布式的、Java 语言是健壮的、Java语言是安全的、Java 语言是体系结构中立的、Java 语言是可移植的、Java 语言是解释型的、Java 是高性能的、Java 语言是多线程的、Java 语言是动态的'),
('HTML学院', 'HTML 指的是超文本标记语言: HyperText Markup Language,它不是一种编程语言,而是一种标记语言,标记语言是一套标记标签 (markup tag),HTML 使用标记标签来描述网页,HTML文档包含了HTML标签及文本内容,HTML文档也叫做 web 页面');
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);
第一套:有关学习的SQL查询
这一套题包含了大部分的查询基础知识,我们平时用的多的语句,在里面都有所展现,如果您没有基础,那就请认真看看吧;如果您学过,并且发现了我的错误,也可以在评论区与我讨论或者私信我,感谢。
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;
select stu_name, stu_sex, stu_birth from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
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 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';
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';
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, stu_sex from tb_student where stu_name regexp '^十.{2}$';
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_addr is null;
select stu_name from tb_student where stu_addr<=>null;
select stu_name from tb_student
where stu_addr is 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 distinctrow stu_addr from tb_student
where stu_addr is not null;
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=0 order by stu_birth desc;
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;
select min(stu_birth) from tb_student;
select max(stu_birth) from tb_student;
select max(score) from tb_record where cou_id=1111;
select min(score) from tb_record where stu_id=1001;
select avg(score) from tb_record where cou_id=1111;
select avg(score) from tb_record where stu_id=1001;
select sum(score) / count(cou_id) from tb_record where stu_id=1001;
select avg(ifnull(score,0)) from tb_record where stu_id=1001;
select var_pop(score) from tb_record where stu_id=1001;
select std(score) from tb_record where stu_id=1001;
select stu_sex, count(*) from tb_student
group by stu_sex;
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 ;
select stu_id as 学号,round(avg(score),2) as 平均成绩
from tb_record group by stu_id having avg(score)>=90;
select stu_id as 学号, round(avg(score),2) as 平均成绩
from tb_record where cou_id in (1111,2222)
group by stu_id having avg(score)>=90;
set @a=(select min(stu_birth) from tb_student);
select stu_name from tb_student where stu_birth=@a;
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 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 inner join tb_college
on tb_student.col_id=tb_college.col_id;
select stu_name, stu_birth, col_name
from tb_student natural join tb_college;
select stu_name, cou_name, score
from tb_student, tb_course, tb_record
where tb_student.stu_id=tb_record.stu_id and tb_course.cou_id=tb_record.cou_id
having score is not null;
select stu_name, cou_name, score
from tb_student inner join tb_course inner join tb_record
on tb_student.stu_id=tb_record.stu_id and tb_course.cou_id=tb_record.cou_id
having 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 offset 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;
select stu_name, avg_score
from tb_student t1,
( select stu_id,round(avg(score),2) as avg_score
from tb_record group by stu_id ) t2
where t1.stu_id=t2.stu_id;
select stu_name, avg_score
from tb_student as t1 inner join
( select stu_id,round(avg(score),1) as avg_score
from tb_record group by stu_id ) as t2
on t1.stu_id=t2.stu_id;
select stu_name as 学生姓名, 选课数量
from tb_student as t3 inner join
( select stu_id,count(*) as 选课数量
from tb_record group by stu_id ) as t4
on t3.stu_id=t4.stu_id;
select stu_name as 学生姓名, 选课数量
from tb_student as t3 left outer join
( select stu_id,count(*) as 选课数量
from tb_record group by stu_id ) as t4
on t3.stu_id=t4.stu_id;
select stu_name as 学生姓名, ifnull(选课数量,0) as 选课数量
from tb_student as t3 left outer join
( select stu_id,count(*) as 选课数量
from tb_record group by stu_id ) as t4
on t3.stu_id=t4.stu_id;
?
建库建表二
第二个库是有关于工作的,查询这里面的表是很可能会在实际中遇到的,无论是TOP排名还是薪资问题都很常见。
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)
);
insert into tb_emp values
(7800, '曾霜', '总裁', null, 20000, 1200, 20),
(2056, '无一烦', '分析师', 7800, 12800, 1500, 20),
(3088, '骆子翔', '设计师', 2056, 10800, 800, 20),
(3211, '前锋', '程序员', 2056, 8200, null, 20),
(3233, '兆威', '程序员', 2056, 8400, null, 20),
(3251, '麻陨', '程序员', 2056, 8600, null, 20),
(5566, '中场', '会计师', 7800, 7000, 1000, 10),
(5234, '皇亥伯', '出纳', 5566, 3000, null, 10),
(3344, '方朱铭', '销售主管', 7800, 5000, 800, 30),
(1359, '克正冬', '销售员', 3344, 3000, 200, 30),
(4466, '后卫', '销售员', 3344, 3500, null, 30),
(3244, '武宿博', '程序员', 3088, 5200, null, 20),
(3577, '成雨繁', '会计', 5566, 4200, null, 10),
(3588, '门将', '会计', 5566, 4500, null, 10);
第二套:有关工作的SQL查询
第二套题中在起到练习作用的基础上拓展了一些知识,里面有存在性判断、MySQL8引入的窗口函数这样的解决问题的SQL语句。
select sal,ename from tb_emp where sal in (select max(sal) from tb_emp);
select sal,ename from tb_emp where sal>=all(select sal from tb_emp);
select sal,ename from tb_emp as t1
where not exists( select 'x' from tb_emp as t2 where t2.sal>t1.sal );
select ename,(sal+ifnull(comm,0))*13 as a_sal from tb_emp;
select dno as 部门编号,count(*) as 人数 from tb_emp
group by dno;
select dname as 部门名称,ifnull(total,0) as 人数 from tb_dept
left join (select dno,count(*) as total from tb_emp group by dno) as tb_temp
on tb_dept.dno=tb_temp.dno;
select ename,sal from tb_emp
where sal in (select max(sal) from tb_emp where mgr is not null);
select ename,sal from tb_emp
where sal in (select max(sal) from tb_emp where job<>'总裁');
select ename,ifnull(sal,null) from tb_emp
where sal=(select sal from tb_emp order by sal desc limit 1,1);
select ename,ifnull(sal,null) from tb_emp
where sal=(select max(sal) from tb_emp where sal<(select max(sal) from tb_emp));
select ename,sal from tb_emp
where sal > (select avg(sal) from tb_emp);
select ename,t1.dno,sal from tb_emp as t1 inner join
(select dno,avg(sal) as avg_sal from tb_emp group by dno) as t2
on t1.dno=t2.dno and sal>avg_sal;
select ename,sal,dname from tb_emp as t1 inner join tb_dept as t2 inner join
(select dno,max(sal) as max_sal from tb_emp group by dno) as t3
on t1.dno=t2.dno and t1.dno=t3.dno and sal=max_sal;
select ename,sal,dname from tb_emp as t1, tb_dept as t2,
(select dno,max(sal) as max_sal from tb_emp group by dno) as t3
where t1.dno=t2.dno and t1.dno=t3.dno and sal=max_sal;
select ename,job from tb_emp as t1,
(select mgr from tb_emp where mgr is not null group by mgr) as t2
where t1.eno=t2.mgr;
select ename,job from tb_emp
where eno=any(select distinct mgr from tb_emp where mgr is not null);
select ename,job from tb_emp
where eno in (select distinct mgr from tb_emp where mgr is not null);
select ename,job from tb_emp t1
where exists (select 'x'from tb_emp t2 where t1.eno=t2.mgr);
select ename,sal,
row_number() over (order by sal desc) as rn,
rank() over (order by sal desc) as rk,
dense_rank() over (order by sal desc) as drn
from tb_emp;
select ename,sal,rn from
(select ename,sal,row_number() over (order by sal desc) as rn from tb_emp)
tb_temp where rn limit 3 offset 3;
select ename,sal,rk from
( select ename,sal,dense_rank() over (order by sal desc) as rk from tb_emp )
tb_temp where rk between 4 and 6;
select row_num,ename,sal from
( select @a:=@a+1 as row_num,ename,sal
from tb_emp,(select @a:=0) t1 order by sal desc ) t2
where row_num between 4 and 6;
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 rk,ename,sal,dno
from tb_emp ) as tb_temp where rk<=2;
建库建表三
最后一套更加贴近生活,我们每个人应该都购物过吧,无论是不是在互联网时代,消费问题都会引出大量的数据,我们通过这些数据(货单价、客单价)掌握顾客好恶;我们甚至依靠这类数据的趋势,着眼于未来,通向发家致富的路。通过SQL语句的查询获取这类有用的数据也就变的尤为重要。
create database homework default charset utf8mb4;
use homework;
create table tb_product
(
prod_id varchar(50) not null comment '商品号',
category varchar(50) not null comment '种类',
color varchar(10) not null comment '颜色',
weight decimal(10, 2) not null comment '重量',
price integer not null comment '价格',
primary key (prod_id)
) engine=innodb comment '产品表';
insert into tb_product values
('prodA', 'cateA', 'yellow', 5.6, 100),
('prodB', 'cateB', 'red', 3.7, 200),
('prodC', 'cateC', 'blue', 10.3, 300),
('prodD', 'cateD', 'black', 7.8, 400);
create table tb_order
(
id integer not null auto_increment,
order_no varchar(20) not null comment '订单号',
user_id varchar(50) not null comment '用户号',
order_date date not null comment '下单日期',
store varchar(50) not null comment '店铺号',
product varchar(50) not null comment '商品号',
quantity integer not null comment '购买数量',
primary key (id)
) engine=innodb comment '订单表';
insert into tb_order
(order_no, user_id, order_date, store, product, quantity)
values
('D001', 'customerA', '2018-01-01', 'storeA', 'prodA', 1),
('D001', 'customerA', '2018-01-01', 'storeA', 'prodB', 1),
('D001', 'customerA', '2018-01-01', 'storeA', 'prodC', 1),
('D002', 'customerB', '2018-01-12', 'storeB', 'prodB', 1),
('D002', 'customerB', '2018-01-12', 'storeB', 'prodD', 1),
('D003', 'customerC', '2018-01-12', 'storeC', 'prodB', 1),
('D003', 'customerC', '2018-01-12', 'storeC', 'prodC', 1),
('D003', 'customerC', '2018-01-12', 'storeC', 'prodD', 1),
('D004', 'customerA', '2018-01-01', 'storeD', 'prodD', 2),
('D005', 'customerB', '2018-01-23', 'storeB', 'prodA', 1);
create table tb_store
(
store_id varchar(50) not null comment '店铺号',
city varchar(20) not null comment '城市',
primary key (store_id)
) engine=innodb comment '店铺表';
insert into tb_store values
('storeA', 'cityA'),
('storeB', 'cityA'),
('storeC', 'cityB'),
('storeD', 'cityC'),
('storeE', 'cityD'),
('storeF', 'cityB');
第三套:升级-订单SQL查询
这边是难度升级,更复合考题的标准,是有可能会在面试中遇到的SQL语句。虽然只有三道题,但是都很经典,思路不会有太大偏差,方法应该有很多种,如果您对上面的题都拿捏了,那就试一试下面的题吧。
select
user_id,
sum(price * quantity) as 总购买金额,
count(distinct order_no) as 总订单数,
sum(quantity) as 总购买商品数
from ( select order_no, user_id, quantity, price
from tb_order inner join tb_product
on product=prod_id ) as temp
group by user_id having 总购买金额>=800;
select
city as 城市,
count(distinct store_id) as 总店铺数,
count(distinct user_id) as 总购买人数,
ifnull(sum(quantity * price), 0) as 购买总金额
from ( select store_id, city, user_id, quantity, price
from tb_store left join tb_order on store_id=store
left join tb_product on prod_id=product ) as temp
group by city;
select
user_id,
sum(price * quantity) / count(distinct order_no) as 平均订单金额
from ( select order_no, user_id, quantity, price
from tb_order inner join tb_product
on product=prod_id ) temp
where user_id in ( select user_id from tb_order
inner join tb_product on prod_id=product where category='cateA' )
group by user_id;
感谢学习陪伴,您的点赞,评论就是我更新的动力
|