Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并

六、查询DQL⭐⭐⭐⭐⭐(SELECT)

0、查询书写顺序&执行顺序

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第1张图片
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第2张图片
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第3张图片
当selcet中有聚合函数时,看起来是 select 先执行,因为后面having可以用到selcet聚合函数后面的别名

但实际上还是select 后执行,如果不是聚合函数或者其他函数的别名时

测试数据

-- 员工管理(带约束)
create table tb_emp (
    id int unsigned primary key auto_increment comment 'ID',
    username varchar(20) not null unique comment '用户名',
    password varchar(32) default '123456' comment '密码',
    name varchar(10) not null comment '姓名',
    gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',
    image varchar(300) comment '图像',
    job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管',
    entrydate date comment '入职时间',
    create_time datetime not null comment '创建时间',
    update_time datetime not null comment '修改时间'
) comment '员工表';

-- 准备测试数据
INSERT INTO tb_emp (id, username, password, name, gender, image, job, entrydate, create_time, update_time) VALUES
    (1, 'jinyong', '123456', '金庸', 1, '1.jpg', 4, '2000-01-01', '2022-10-27 16:35:33', '2022-10-27 16:35:35'),
    (2, 'zhangwuji', '123456', '张无忌', 1, '2.jpg', 2, '2015-01-01', '2022-10-27 16:35:33', '2022-10-27 16:35:37'),
    (3, 'yangxiao', '123456', '杨逍', 1, '3.jpg', 2, '2008-05-01', '2022-10-27 16:35:33', '2022-10-27 16:35:39'),
    (4, 'weiyixiao', '123456', '韦一笑', 1, '4.jpg', 2, '2007-01-01', '2022-10-27 16:35:33', '2022-10-27 16:35:41'),
    (5, 'changyuchun', '123456', '常遇春', 1, '5.jpg', 2, '2012-12-05', '2022-10-27 16:35:33', '2022-10-27 16:35:43'),
    (6, 'xiaozhao', '123456', '小昭', 2, '6.jpg', 3, '2013-09-05', '2022-10-27 16:35:33', '2022-10-27 16:35:45'),
    (7, 'jixiaofu', '123456', '纪晓芙', 2, '7.jpg', 1, '2005-08-01', '2022-10-27 16:35:33', '2022-10-27 16:35:47'),
    (8, 'zhouzhiruo', '123456', '周芷若', 2, '8.jpg', 1, '2014-11-09', '2022-10-27 16:35:33', '2022-10-27 16:35:49'),
    (9, 'dingminjun', '123456', '丁敏君', 2, '9.jpg', 1, '2011-03-11', '2022-10-27 16:35:33', '2022-10-27 16:35:51'),
    (10, 'zhaomin', '123456', '赵敏', 2, '10.jpg', 1, '2013-09-05', '2022-10-27 16:35:33', '2022-10-27 16:35:53'),
    (11, 'luzhangke', '123456', '鹿杖客', 1, '11.jpg', 2, '2007-02-01', '2022-10-27 16:35:33', '2022-10-27 16:35:55'),
    (12, 'hebiweng', '123456', '鹤笔翁', 1, '12.jpg', 2, '2008-08-18', '2022-10-27 16:35:33', '2022-10-27 16:35:57'),
    (13, 'fangdongbai', '123456', '方东白', 1, '13.jpg', 1, '2012-11-01', '2022-10-27 16:35:33', '2022-10-27 16:35:59'),
    (14, 'zhangsanfeng', '123456', '张三丰', 1, '14.jpg', 2, '2002-08-01', '2022-10-27 16:35:33', '2022-10-27 16:36:01'),
    (15, 'yulianzhou', '123456', '俞莲舟', 1, '15.jpg', 2, '2011-05-01', '2022-10-27 16:35:33', '2022-10-27 16:36:03'),
    (16, 'songyuanqiao', '123456', '宋远桥', 1, '16.jpg', 2, '2010-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:05'),
    (17, 'chenyouliang', '12345678', '陈友谅', 1, '17.jpg', null, '2015-03-21', '2022-10-27 16:35:33', '2022-10-27 16:36:07'),
    (18, 'zhang1', '123456', '张一', 1, '2.jpg', 2, '2015-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:09'),
    (19, 'zhang2', '123456', '张二', 1, '2.jpg', 2, '2012-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:11'),
    (20, 'zhang3', '123456', '张三', 1, '2.jpg', 2, '2018-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:13'),
    (21, 'zhang4', '123456', '张四', 1, '2.jpg', 2, '2015-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:15'),
    (22, 'zhang5', '123456', '张五', 1, '2.jpg', 2, '2016-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:17'),
    (23, 'zhang6', '123456', '张六', 1, '2.jpg', 2, '2012-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:19'),
    (24, 'zhang7', '123456', '张七', 1, '2.jpg', 2, '2006-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:21'),
    (25, 'zhang8', '123456', '张八', 1, '2.jpg', 2, '2002-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:23'),
    (26, 'zhang9', '123456', '张九', 1, '2.jpg', 2, '2011-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:25'),
    (27, 'zhang10', '123456', '张十', 1, '2.jpg', 2, '2004-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:27'),
    (28, 'zhang11', '123456', '张十一', 1, '2.jpg', 2, '2007-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:29'),
    (29, 'zhang12', '123456', '张十二', 1, '2.jpg', 2, '2020-01-01', '2022-10-27 16:35:33', '2022-10-27 16:36:31');

1、单表查询

1)查询字段/设置别名/去除重复记录

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第4张图片
练习

-- 案例1:查询指定字段 name,entrydate并返回
SELECT name,entrydate FROM tb_emp;


-- 案例2:查询返回所有字段
SELECT * FROM tb_emp;

-- `*`号代表查询所有字段,在实际开发中尽量少用(不直观、影响效率)


-- 案例3:查询所有员工的 name,entrydate,并起别名(姓名、入职日期)
-- 方式1:
SELECT name AS 姓名, entrydate AS 入职日期 FROM tb_emp;
-- 方式2: 别名中有特殊字符时,使用''或""包含
SELECT name AS '姓 名', entrydate AS '入职日期' FROM tb_emp;
-- 方式3:
SELECT name AS "姓名", entrydate AS "入职日期" FROM tb_emp;
-- 方式4:去掉as
SELECT name 姓名, entrydate 入职日期 FROM tb_emp;


-- 案例4:查询已有的员工关联了哪几种职位(不要重复)
SELECT DISTINCT job FROM tb_emp;

-- 案例5:去除职位和入职日期重复的查询(必须job和entrydate都一样)
SELECT DISTINCT job,entrydate FROM tb_emp;

-- 案例6://假如有个学生成绩表student(id,NAME,chinese,english,math) 
-- 统计每个学生的总分
SELECT `name`, (chinese+english+math) FROM student;

【注意】
DISTINCT修饰的字段如果有多个,那么只有当这些字段同时相同时才会被视为重复数据筛掉

2)条件查询where/比较和逻辑运算符

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第5张图片
常用的比较运算符如下:

比较运算符 功能
> 大于
>= 大于等于
< 小于
<= 小于等于
= 等于
<> 或 != 不等于
between … and … 在某个范围之内(含最小、最大值)
in(…) 在in之后的列表中的值,多选一
like 占位符 模糊匹配(_匹配单个字符, %匹配任意个字符)
is null 是null

常用的逻辑运算符如下:

逻辑运算符 功能
and 或 && 并且 (多个条件同时成立)
or 或 || 或者 (多个条件任意一个成立)
not 或 ! 非 , 不是

【练习】


-- 1:查询 姓名 为 杨逍 的员工
SELECT *  FROM tb_emp WHERE name='杨逍';

-- 2:查询 id小于等于5 的员工信息
SELECT * FROM tb_emp WHERE id <= 5;

-- 3:查询 没有分配职位 的员工信息
SELECT *  FROM tb_emp WHERE job IS NULL;

-- 4:查询 有职位 的员工信息
SELECT * FROM tb_emp WHERE job IS NOT NULL;

-- 5:查询 密码不等于 '123456' 的员工信息
SELECT * FROM tb_emp WHERE password != 123456;

-- 6:查询 入职日期 在 '2000-01-01' (包含) 到 '2010-01-01'(包含) 之间的员工信息
SELECT * FROM tb_emp WHERE entrydate BETWEEN '2000-01-01' AND '2010-01-01';

-- 7:查询 入职时间 在 '2000-01-01' (包含) 到 '2010-01-01'(包含) 之间 且 性别为女 的员工信息
SELECT * FROM tb_emp WHERE entrydate BETWEEN '2000-01-01' AND '2010-01-01' AND gender = '2';

-- 8:查询 职位是 2 (讲师), 3 (学工主管), 4 (教研主管) 的员工信息
SELECT * FROM tb_emp WHERE job = 2 AND job = 3 AND job = 4;
SELECT * FROM tb_emp WHERE job BETWEEN 2 AND 4;
SELECT * FROM tb_emp WHERE job IN (2,3,4);

-- 9:查询 姓名 为两个字的员工信息
SELECT * FROM tb_emp WHERE name LIKE '__';

-- 10:查询 姓 '张' 的员工信息
SELECT * FROM tb_emp WHERE name LIKE '张%';

4)分组查询group by/聚合函数

  • ① 聚合函数
    Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第6张图片

常用聚合函数:

函数 功能
count 统计数量
max 最大值
min 最小值
avg 平均值
sum 求和

格式化函数:
FORMAT() 函数用于对字段的显示进行格式化。
语法

SELECT FORMAT(column_name,format) FROM table_name;

FORMAT(X,D):强制保留D位小数,整数部分超过三位的时候以逗号分割,并且返回的结果是string类型的

SELECT FORMAT(423423234.65634453,2);

结果: 423,423,234.65

【练习】

-- 1: 统计该企业员工数量
SELECT COUNT(*) FROM tb_emp; -- 推荐
SELECT COUNT(id) FROM tb_emp;
-- 注意不能用SELECT COUNT(job),因为job中有一个null值,而聚合函数不对null值进行计算

-- 2: 统计该企业最早入职的员工
SELECT MIN(entrydate) FROM tb_emp;

-- 3: 统计该企业最迟入职的员工
SELECT MAX(entrydate) FROM tb_emp;

-- 4: 统计该企业员工 ID 的平均值
SELECT AVG(id) FROM tb_emp;

-- 假如有个学生成绩表student(id,NAME,chinese,english,math) 
-- 统计每个学生的总分平均分,强制保留两位小数
SELECT FORMAT(AVG(math + english + chinese),2) FROM student;

-- 5: 统计该企业员工的 ID 之和
SELECT SUM(id) FROM tb_emp;

-- 6: 统计没有设置职位的员工数量
-- 1)减法
SELECT COUNT(*)-COUNT(job) FROM tb_emp;
-- 2)加法:job为null,统计数量就加1
SELECT COUNT(IF(job IS NULL , 1 , NULL)) FROM tb_emp;

-- 7: 统计职位种数
SELECT COUNT(DISTINCT(job)) FROM tb_emp;


-- 8:显示每个部门的每种岗位的平均工资和最低工资
SELECT AVG(sal), MIN(sal) , deptno, job 
	FROM  emp GROUP BY deptno, job;


Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第7张图片

  • ② 分组查询
    在这里插入图片描述
-- 1:根据性别分组 , 统计男性和女性员工的数量
SELECT gender, COUNT(*) FROM tb_emp GROUP BY gender;

-- 2:查询入职时间在 '2015-01-01' (包含) 以前的员工 , 并对结果根据职位分组 , 获取员工数量大于等于2的职位
SELECT job,COUNT(*) 
FROM tb_emp 
WHERE entrydate <= '2015-01-01' 
GROUP BY job 
HAVING COUNT(*) >= 2;

where与having区别(面试题)

  • 执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤。
  • 判断条件不同:where不能对聚合函数进行判断,而having可以。

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第8张图片

5)排序查询order by

在这里插入图片描述

  • 排序方式:

    • ASC :升序(默认值)

    • DESC:降序

【练习】

-- 1:根据入职时间, 对员工进行升序排序
SELECT * FROM tb_emp ORDER BY entrydate;

-- 2:根据入职时间,对员工进行降序排序
SELECT * FROM tb_emp ORDER BY entrydate DESC;

-- 3:根据入职时间对公司的员工进行升序排序,入职时间相同,再按照更新时间进行降序排序
SELECT * FROM tb_emp ORDER BY entrydate , update_time DESC;

在这里插入图片描述

6)分页查询limit

日常我们在网站中看到的各种各样的分页条,后台也都需要借助于数据库的分页操作。
在这里插入图片描述
【练习】

-- 1:从起始索引0开始查询员工数据, 每页展示5条记录
SELECT * FROM tb_emp LIMIT 0 , 5;
-- 查询第一页时,起始索引可以省略
SELECT * FROM tb_emp LIMIT 5;

-- 2:查询 第1页 员工数据, 每页展示5条记录
SELECT * FROM tb_emp LIMIT 0 , 5;
-- 查询第一页时,起始索引可以省略
SELECT * FROM tb_emp LIMIT 5;

-- 3:查询 第2页 员工数据, 每页展示5条记录
SELECT * FROM tb_emp LIMIT 5, 5;

-- 4:查询 第3页 员工数据, 每页展示5条记录
SELECT * FROM tb_emp LIMIT 10 , 5;

【起始索引计算⭐⭐⭐】
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第9张图片

7)DQL练习/流程控制函数

案例一:根据需求完成员工管理的条件分页查询
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第10张图片

分析:根据输入的条件,查询第1页数据

  1. 在员工管理的列表上方有一些查询条件:员工姓名、员工性别,员工入职时间(开始时间~结束时间)

    • 姓名:张
    • 性别:男
    • 入职时间:2000-01-01 ~ 2015-12-31
  2. 除了查询条件外,在列表的下面还有一个分页条,这就涉及到了分页查询

    • 查询第1页数据(每页显示10条数据)
  3. 基于查询的结果,按照修改时间进行降序排序

结论:条件查询 + 分页查询 + 排序查询

SELECT id, username, password, name, gender, image, job, entrydate, create_time, update_time
FROM tb_emp
WHERE name LIKE '张%' AND gender = 1 AND entrydate BETWEEN '2000-01-01' AND '2015-12-31'
ORDER BY update_time DESC
LIMIT 0,10

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第11张图片


案例二:根据需求完成员工信息的统计
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第12张图片

分析:以上信息统计在开发中也叫图形报表(将统计好的数据以可视化的形式展示出来)

  • 员工性别统计:以饼状图的形式展示出企业男性员人数和女性员工人数
    • 只要查询出男性员工和女性员工各自有多少人就可以了
  • 员工职位统计:以柱状图的形式展示各职位的在岗人数
    • 只要查询出各个职位有多少人就可以了

【⭐】MySQL流程控制函数(详解在下面的函数详解中)
在这里插入图片描述

-- 2-1:查询出男性员工和女性员工各自有多少人
SELECT IF(gender = 1, '男性员工', '女性员工') AS '姓名', COUNT(*) AS '人数'
FROM tb_emp
GROUP BY gender;

-- 2-2:查询出各个职位有多少人
SELECT (CASE job
            WHEN 1 THEN '班主任'
            WHEN 2 THEN '讲师'
            WHEN 3 THEN '学工主管'
            WHEN 4 THEN '教研主管'
            ELSE '未分配职位'
        END)     AS '职位',
        COUNT(*) AS '人数'
FROM tb_emp
GROUP BY job;

2、函数

0、FROM DUAL

DUAL简单的说就是一个空表bai,只有一行一列,常用来计算常数

1、聚合函数

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第13张图片

常用聚合函数:

函数 功能
count 统计数量
max 最大值
min 最小值
avg 平均值
sum 求和

2、字符串函数

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第14张图片

SUBSTRING第三个参数如果不写,默认是取到最后一个

-- 演示字符串相关函数的使用  , 使用emp表来演示
-- CHARSET(str)	返回字串字符集
SELECT CHARSET(ename) FROM emp;
-- CONCAT (string2  [,... ])	连接字串, 将多个列拼接成一列
SELECT CONCAT(ename, ' 工作是 ', job) FROM emp;
 
-- INSTR (string ,substring )	返回substring在string中出现的位置,没有返回0
-- dual 亚元表, 系统表 可以作为测试表使用
SELECT INSTR('hanshunping', 'ping') FROM DUAL; 
 
-- UCASE (string2 )	转换成大写
SELECT UCASE(ename) FROM emp;
 
-- LCASE (string2 )	转换成小写
 
SELECT LCASE(ename) FROM emp;
-- LEFT (string2 ,length )	从string2中的左边起取length个字符
-- RIGHT (string2 ,length )	从string2中的右边起取length个字符
SELECT LEFT(ename, 2) FROM emp;
 
-- LENGTH (string )	string长度[按照字节]
SELECT LENGTH(ename) FROM emp;
-- REPLACE (str ,search_str ,replace_str ) 	
-- 在str中用replace_str替换search_str
-- 如果是manager 就替换成 经理
SELECT ename, REPLACE(job,'MANAGER', '经理')  FROM emp;
 
-- STRCMP (string1 ,string2 )	逐字符比较两字串大小
SELECT STRCMP('hsp', 'hsp') FROM DUAL;
-- SUBSTRING (str , position  [,length ])	
-- 从str的position开始【从1开始计算】,取length个字符
-- 从ename 列的第一个位置开始取出2个字符
SELECT SUBSTRING(ename, 1, 2) FROM emp;
 
-- LTRIM (string2 ) RTRIM (string2 )  TRIM(string)
-- 去除前端空格或后端空格
SELECT LTRIM('  韩顺平教育') FROM DUAL;
SELECT RTRIM('韩顺平教育   ') FROM DUAL;
SELECT TRIM('    韩顺平教育   ') FROM DUAL;
 
-- 练习: 以首字母小写的方式显示所有员工emp表的姓名
-- 方法1 
-- 思路先取出ename 的第一个字符,转成小写的
-- 把他和后面的字符串进行拼接输出即可
 
SELECT CONCAT(LCASE(SUBSTRING(ename,1,1)),  SUBSTRING(ename,2)) AS new_name
	FROM emp;  
 
SELECT CONCAT(LCASE(LEFT(ename,1)),  SUBSTRING(ename,2)) AS new_name
	FROM emp; 

3、数学函数

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第15张图片

-- 演示数学相关函数
 
-- ABS(num)	绝对值
SELECT ABS(-10) FROM DUAL;
-- BIN (decimal_number )十进制转二进制
SELECT BIN(10) FROM DUAL;
-- CEILING (number2 )	向上取整, 得到比num2 大的最小整数
SELECT CEILING(-1.1) FROM DUAL;
 
-- CONV(number2,from_base,to_base)	进制转换
-- 下面的含义是 8 是十进制的8, 转成 2进制输出
SELECT CONV(8, 10, 2) FROM DUAL;
-- 下面的含义是 8 是16进制的8, 转成 2进制输出
SELECT CONV(16, 16, 10) FROM DUAL;
 
-- FLOOR (number2 )	向下取整,得到比 num2 小的最大整数
SELECT FLOOR(-1.1) FROM DUAL;
 
-- FORMAT (number,decimal_places )	保留小数位数(四舍五入)
SELECT FORMAT(78.125458,2) FROM DUAL;
 
-- HEX (DecimalNumber )	转十六进制
 
-- LEAST (number , number2  [,..])	求最小值
SELECT LEAST(0,1, -10, 4) FROM DUAL;
-- MOD (numerator ,denominator )	求余
SELECT MOD(10, 3) FROM DUAL;
 
-- RAND([seed])	RAND([seed]) 返回随机数 其范围为 0 ≤ v ≤ 1.0
-- 老韩说明
-- 1. 如果使用 rand() 每次返回不同的随机数 ,在 0 ≤ v ≤ 1.0
-- 2. 如果使用 rand(seed) 返回随机数, 范围 0 ≤ v ≤ 1.0, 如果seed不变,
--    该随机数也不变了
SELECT RAND() FROM DUAL;
SELECT RAND(3) FROM DUAL;
 
SELECT CURRENT_TIMESTAMP() FROM DUAL;

4、日期函数

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第16张图片
增加几个:
FROM_DAYS(number) //从数字日期值返回日期
TO_DAYS(date) //返回日期和年份0之间的天数(日期“0000-00-00”)

NOW() 返回年月日时分秒
CURRENT_DATE() 返回年月日
CURRENT_TIME() 返回时分秒
CURRENT_TIMESTAMP() 返回年月日时分秒
-- 日期时间相关函数
 
-- CURRENT_DATE (  )	当前日期
SELECT CURRENT_DATE() FROM DUAL;
-- CURRENT_TIME (  )	当前时间
SELECT CURRENT_TIME()  FROM DUAL;
-- CURRENT_TIMESTAMP (  ) 当前时间戳
SELECT CURRENT_TIMESTAMP()  FROM DUAL;

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第17张图片

-- 创建测试表 信息表
CREATE TABLE mes(
	id INT , 
	content VARCHAR(30), 
	send_time DATETIME);
	
	
-- 添加一条记录
INSERT INTO mes 
	VALUES(1, '北京新闻', CURRENT_TIMESTAMP()); 
INSERT INTO mes VALUES(2, '上海新闻', NOW());
INSERT INTO mes VALUES(3, '广州新闻', NOW());
 
SELECT * FROM mes;
SELECT NOW() FROM DUAL;
 
-- 【应用实例】
-- 1. 显示所有新闻信息,发布日期只显示 日期,不用显示时间.
SELECT id, content, DATE(send_time) 
	FROM mes;
	
-- 2. 请查询在10分钟内发布的新闻, 思路一定要梳理一下.
SELECT * 
	FROM mes
	WHERE DATE_ADD(send_time, INTERVAL 10 MINUTE) >= NOW()
 
SELECT * 
	FROM mes
	WHERE send_time >= DATE_SUB(NOW(), INTERVAL 10 MINUTE) 
 
 
-- 3. 请在mysql 的sql语句中求出 2011-11-11 和 1990-1-1 相差多少天
SELECT DATEDIFF('2011-11-11', '1990-01-01') FROM DUAL;

-- 4. 请用mysql 的sql语句求出你活了多久(以天数方式呈现)? [练习] 1986-11-11 出生
SELECT DATEDIFF(NOW(), '1986-11-11') FROM DUAL;
-- 请用mysql 的sql语句求出你活了多久(以年月日方式呈现)? [练习] 1986-11-11 出生
SELECT FROM_DAYS(DATEDIFF(NOW() , '1986-11-11'))
FROM DUAL;

-- 如果你能活80岁,求出你还能活多少天.[练习] 1986-11-11 出生
-- 先求出活80岁 时, 是什么日期 X
-- 然后在使用 datediff(x, now()); 1986-11-11->datetime
-- INTERVAL 80 YEAR : YEAR 可以是 年月日,时分秒
-- '1986-11-11' 可以date,datetime timestamp 
SELECT DATEDIFF(DATE_ADD('1986-11-11', INTERVAL 80 YEAR), NOW()) 
	FROM DUAL;
	
SELECT TIMEDIFF('10:11:11', '06:10:10') FROM DUAL;


在这里插入图片描述

-- YEAR|Month|DAY| DATE (datetime )
SELECT YEAR(NOW()) FROM DUAL;
SELECT MONTH(NOW()) FROM DUAL;
SELECT DAY(NOW()) FROM DUAL;
SELECT MONTH('2013-11-10') FROM DUAL;
-- unix_timestamp() : 返回的是1970-1-1 到现在的秒数
SELECT UNIX_TIMESTAMP() FROM DUAL;
-- FROM_UNIXTIME() : 可以把一个unix_timestamp 秒数[时间戳],转成指定格式的日期
-- %Y-%m-%d 格式是规定好的,表示年月日
-- 意义:在开发中,可以存放一个整数,然后表示时间,通过FROM_UNIXTIME转换
-- 下面1618483484就是一个秒数,能转换成后面Y-m-d的时间形式
SELECT FROM_UNIXTIME(1618483484, '%Y-%m-%d') FROM DUAL;
SELECT FROM_UNIXTIME(1618483100, '%Y-%m-%d %H:%i:%s') FROM DUAL;

5、加密函数

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第18张图片

-- 演示加密函数和系统函数
 
-- 1. USER()	查询用户
-- 可以查看登录到mysql的有哪些用户,以及登录的IP
SELECT USER() FROM DUAL; -- 用户@IP地址

-- 2. DATABASE()	查询当前使用数据库名称
SELECT DATABASE();
 
-- 3. MD5(str)	为字符串算出一个 MD5 32的字符串,常用(用户密码)加密
-- root 密码是 hsp -> 加密md5 -> 在数据库中存放的是加密后的密码
SELECT MD5('hsp') FROM DUAL;
SELECT LENGTH(MD5('hsp')) FROM DUAL;
 
-- 演示用户表,存放密码时,是md5
CREATE TABLE hsp_user
	(id INT , 
	`name` VARCHAR(32) NOT NULL DEFAULT '', 
	pwd CHAR(32) NOT NULL DEFAULT '');
INSERT INTO hsp_user 
	VALUES(100, '韩顺平', MD5('hsp')); -- 【⭐存放密码时使用MD5编码】
SELECT * FROM hsp_user; -- csdn
 
SELECT * FROM hsp_user  -- SQL注入问题
	WHERE `name`='韩顺平' AND pwd = MD5('hsp')  
 
 
-- 4. PASSWORD(str) -- 加密函数, 从原文密码str 计算并返回密码字符串
-- 通常用于对mysql数据库的用户密码加密
-- MySQL数据库的用户密码就是 PASSWORD 函数加密
SELECT PASSWORD('hsp') FROM DUAL; -- 数据库的 *81220D972A52D4C51BB1C37518A2613706220DAC
 
 
-- select * from mysql.user \G 	
-- mysql.user 表示 mysql数据库中的user表 
SELECT * FROM mysql.user

6、流程控制函数

在这里插入图片描述
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第19张图片
在这里插入图片描述

3、多表查询

数据准备

#建议:创建新的数据库
create database db04;
use db04;

-- 部门表
create table tb_dept
(
    id          int unsigned primary key auto_increment comment '主键ID',
    name        varchar(10) not null unique comment '部门名称',
    create_time datetime    not null comment '创建时间',
    update_time datetime    not null comment '修改时间'
) comment '部门表';
-- 部门表测试
insert into tb_dept (id, name, create_time, update_time)
values (1, '学工部', now(), now()),
       (2, '教研部', now(), now()),
       (3, '咨询部', now(), now()),
       (4, '就业部', now(), now()),
       (5, '人事部', now(), now());

-- 员工表
create table tb_emp
(
    id          int unsigned primary key auto_increment comment 'ID',
    username    varchar(20)      not null unique comment '用户名',
    password    varchar(32) default '123456' comment '密码',
    name        varchar(10)      not null comment '姓名',
    gender      tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',
    image       varchar(300) comment '图像',
    job         tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师',
    entrydate   date comment '入职时间',
    dept_id     int unsigned comment '部门ID',
    create_time datetime         not null comment '创建时间',
    update_time datetime         not null comment '修改时间'
) comment '员工表';
-- 员工表测试数据
INSERT INTO tb_emp(id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time) 
VALUES 
(1,'jinyong','123456','金庸',1,'1.jpg',4,'2000-01-01',2,now(),now()),
(2,'zhangwuji','123456','张无忌',1,'2.jpg',2,'2015-01-01',2,now(),now()),
(3,'yangxiao','123456','杨逍',1,'3.jpg',2,'2008-05-01',2,now(),now()),
(4,'weiyixiao','123456','韦一笑',1,'4.jpg',2,'2007-01-01',2,now(),now()),
(5,'changyuchun','123456','常遇春',1,'5.jpg',2,'2012-12-05',2,now(),now()),
(6,'xiaozhao','123456','小昭',2,'6.jpg',3,'2013-09-05',1,now(),now()),
(7,'jixiaofu','123456','纪晓芙',2,'7.jpg',1,'2005-08-01',1,now(),now()),
(8,'zhouzhiruo','123456','周芷若',2,'8.jpg',1,'2014-11-09',1,now(),now()),
(9,'dingminjun','123456','丁敏君',2,'9.jpg',1,'2011-03-11',1,now(),now()),
(10,'zhaomin','123456','赵敏',2,'10.jpg',1,'2013-09-05',1,now(),now()),
(11,'luzhangke','123456','鹿杖客',1,'11.jpg',5,'2007-02-01',3,now(),now()),
(12,'hebiweng','123456','鹤笔翁',1,'12.jpg',5,'2008-08-18',3,now(),now()),
(13,'fangdongbai','123456','方东白',1,'13.jpg',5,'2012-11-01',3,now(),now()),
(14,'zhangsanfeng','123456','张三丰',1,'14.jpg',2,'2002-08-01',2,now(),now()),
(15,'yulianzhou','123456','俞莲舟',1,'15.jpg',2,'2011-05-01',2,now(),now()),
(16,'songyuanqiao','123456','宋远桥',1,'16.jpg',2,'2007-01-01',2,now(),now()),
(17,'chenyouliang','123456','陈友谅',1,'17.jpg',NULL,'2015-03-21',NULL,now(),now());

1)笛卡尔积

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第20张图片
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第21张图片
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第22张图片
可以看出,在组合出来的笛卡尔积中,只有 detp_id = id 时才是有效数据

所以用where来消除无效的笛卡尔积

SELECT * 
FROM tb_emp,tb_dept 
WHERE detp_id = id;

2)连接

① 分类

  1. 连接查询

    • 内连接:相当于查询A、B交集部分数据

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第23张图片

  1. 外连接

    • 左外连接:查询左表所有数据(行数据)(包括两张表交集部分数据)

    • 右外连接:查询右表所有数据(行数据)(包括两张表交集部分数据)

  2. 子查询

② 内连接

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第24张图片

select tb_emp.name , tb_dept.name -- 分别查询两张表中的数据
from tb_emp , tb_dept -- 关联两张表
where tb_emp.dept_id = tb_dept.id; -- 消除笛卡尔积
  • 显式内连接实现
select tb_emp.name , tb_dept.name
from tb_emp inner join tb_dept
on tb_emp.dept_id = tb_dept.id;

② 自连接(也属于内连接)

  • 思考题: 显示公司员工名字和他的上级的名字
    Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第25张图片
-- 多表查询的 自连接
 
-- 老韩分析: 员工名字 在emp, 上级的名字的名字 emp
-- 员工和上级是通过 emp表的 mgr 列关联
-- 这里老师小结:
-- 自连接的特点 1. 把同一张表当做两张表使用
--       2. 需要给表取别名 表名  表别名(注意别名在FROM取,因为FROM最先执行) 
-- 		 3. 一旦为表起了别名,就不能再使用表名来指定对应的字段了,此时只能够使用别名来指定字段。 
--		 3. 列名不明确,可以指定列的别名 列名 as 列的别名		
SELECT worker.ename AS '职员名' ,  boss.ename AS '上级名'
	FROM emp worker, emp boss
	WHERE worker.mgr = boss.empno;
SELECT * FROM emp;

④ 外连接

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第26张图片

【⭐】谁在left/right join左边谁就是左表

案例:查询员工表中所有员工的姓名, 和对应的部门名称

-- 左外连接:以left join关键字左边的表为主表,查询主表中所有数据,以及和主表匹配的右边表中的数据
select emp.name , dept.name
from tb_emp AS emp left join tb_dept AS dept 
     on emp.dept_id = dept.id;

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第27张图片

案例:查询部门表中所有部门的名称, 和对应的员工名称

-- 右外连接
select e.name , d.name
from tb_emp AS e right join  tb_dept AS d
     on e.dept_id = d.id;

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第28张图片

注意事项:

左外连接和右外连接是可以相互替换的,只需要调整连接查询时SQL语句中表的先后顺序就可以了。而我们在日常开发使用时,更偏向于左外连接。

⑤ 子查询

Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第29张图片
Java笔记(三十一):MySQL(中)--查询DQL、单表查询、函数、多表查询、查询结果合并_第30张图片

a)标量子查询(查询结果:单行单列)

子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询。

常用的操作符: = <> > >= < <=

案例1:查询"教研部"的所有员工信息

可以将需求分解为两步:

  1. 查询 “教研部” 部门ID
  2. 根据 “教研部” 部门ID,查询员工信息
-- 1.查询"教研部"部门ID
select id from tb_dept where name = '教研部';    #查询结果:2
-- 2.根据"教研部"部门ID, 查询员工信息
select * from tb_emp where dept_id = 2;

-- 合并出上两条SQL语句
select * from tb_emp where dept_id = (select id from tb_dept where name = '教研部');
b)列子查询

子查询返回的结果是一列(可以是多行),这种子查询称为列子查询。

常用的操作符:

操作符 描述
IN 在指定的集合范围之内,多选一
NOT IN 不在指定的集合范围之内
ALL 包括查询后的所有数据
ANY 包括查询后的任何数据

案例:查询"教研部"和"咨询部"的所有员工信息

分解为以下两步:

  1. 查询 “销售部” 和 “市场部” 的部门ID
  2. 根据部门ID, 查询员工信息
-- 1.查询"销售部"和"市场部"的部门ID
select id from tb_dept where name = '教研部' or name = '咨询部';    #查询结果:3,2
-- 2.根据部门ID, 查询员工信息
select * from tb_emp where dept_id in (3,2);

-- 合并以上两条SQL语句
select * from tb_emp where dept_id in (select id from tb_dept where name = '教研部' or name = '咨询部');


-- all 和 any的使用
 
-- 请思考:显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
 
SELECT ename, sal, deptno
	FROM emp
	WHERE sal > ALL(
		SELECT sal 
			FROM emp
			WHERE deptno = 30
		)
-- 可以这样写:比最高工资高就可以保证比所有员工工资都高
SELECT ename, sal, deptno
	FROM emp
	WHERE sal > (
		SELECT MAX(sal) 
			FROM emp
			WHERE deptno = 30
		) 
 
-- 请思考:如何显示工资比部门30的其中一个员工的工资高的员工的姓名、工资和部门号(至少一个)
 
SELECT ename, sal, deptno
	FROM emp
	WHERE sal > any(
		SELECT sal 
			FROM emp
			WHERE deptno = 30
		)
 
 -- 或者:比最小工资的高就可以保证比至少一个员工工资高
 SELECT ename, sal, deptno
	FROM emp
	WHERE sal > (
		SELECT min(sal) 
			FROM emp
			WHERE deptno = 30
		)
c)行子查询

子查询返回的结果是一行(可以是多列),这种子查询称为行子查询。

常用的操作符:= 、<> 、IN 、NOT IN

案例:查询与"韦一笑"的入职日期及职位都相同的员工信息

可以拆解为两步进行:

  1. 查询 “韦一笑” 的入职日期 及 职位
  2. 查询与"韦一笑"的入职日期及职位相同的员工信息
-- 查询"韦一笑"的入职日期 及 职位
select entrydate , job from tb_emp where name = '韦一笑';  #查询结果: 2007-01-01 , 2
-- 查询与"韦一笑"的入职日期及职位相同的员工信息
select * from tb_emp where (entrydate,job) = ('2007-01-01',2);

-- 合并以上两条SQL语句
select * from tb_emp where (entrydate,job) = (select entrydate , job from tb_emp where name = '韦一笑');
d)表子查询

子查询返回的结果是多行多列,常作为临时表,这种子查询称为表子查询。

案例:查询入职日期是 “2006-01-01” 之后的员工信息 , 及其部门信息

分解为两步执行:

  1. 查询入职日期是 “2006-01-01” 之后的员工信息
  2. 基于查询到的员工信息,在查询对应的部门信息
select * from emp where entrydate > '2006-01-01';

-- 查询结果作为一张临时表,可以FROM 这张表,也可以给它取别名 e
select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id ;
e)子查询练习
-- 子查询练习
 
-- 请思考:查找每个部门工资高于本部门平均工资的人的资料
-- 这里要用到数据查询的小技巧,把一个子查询当作一个临时表使用
 
-- 1. 先得到每个部门的 部门号和 对应的平均工资
 
SELECT deptno, AVG(sal) AS avg_sal
	FROM emp GROUP BY deptno
	
-- 2. 把上面的结果当做子查询, 和 emp 进行多表查询
--    
SELECT ename, sal, temp.avg_sal, emp.deptno
	FROM emp, (
		SELECT deptno, AVG(sal) AS avg_sal
		FROM emp 
		GROUP BY deptno
	) temp 
	where emp.deptno = temp.deptno and emp.sal > temp.avg_sal
	
-- 查找每个部门工资最高的人的详细资料
 
SELECT ename, sal, temp.max_sal, emp.deptno
	FROM emp, (
		SELECT deptno, max(sal) AS max_sal
		FROM emp 
		GROUP BY deptno
	) temp 
	WHERE emp.deptno = temp.deptno AND emp.sal = temp.max_sal
	
 
-- 查询每个部门的信息(包括:部门名,编号,地址)和人员数量,我们一起完成。
 
-- 1. 部门名,编号,地址 来自 dept表
-- 2. 各个部门的人员数量 -》 构建一个临时表
 
select count(*), deptno 
	from emp
	group by deptno;
	
 
select dname, dept.deptno, loc , tmp.per_num as '人数'
	from dept, (
		SELECT COUNT(*) as per_num, deptno 
		FROM emp
		GROUP BY deptno
	) tmp 
	where tmp.deptno = dept.deptno
 
-- 还有一种写法 表.* 表示将该表所有列都显示出来, 可以简化sql语句
-- 在多表查询中,当多个表的列不重复时,才可以直接写列名
 
SELECT tmp.* , dname, loc
	FROM dept, (
		SELECT COUNT(*) AS per_num, deptno 
		FROM emp
		GROUP BY deptno
	) tmp 
	WHERE tmp.deptno = dept.deptno

3)案例

数据准备

-- 分类表
create table category(
    id int unsigned primary key auto_increment comment '主键ID',
    name varchar(20) not null unique comment '分类名称',
    type tinyint unsigned not null comment '类型 1 菜品分类 2 套餐分类',
    sort tinyint unsigned not null comment '顺序',
    status tinyint unsigned not null default 0 comment '状态 0 禁用,1 启用',
    create_time datetime not null comment '创建时间',
    update_time datetime not null comment '更新时间'
) comment '分类' ;

-- 菜品表
create table dish(
    id int unsigned primary key auto_increment comment '主键ID',
    name varchar(20) not null unique comment '菜品名称',
    category_id int unsigned not null comment '菜品分类ID',
    price decimal(8, 2) not null comment '菜品价格',
    image varchar(300) not null comment '菜品图片',
    description varchar(200) comment '描述信息',
    status tinyint unsigned not null default 0 comment '状态, 0 停售 1 起售',
    create_time datetime not null comment '创建时间',
    update_time datetime not null comment '更新时间'
) comment '菜品';

-- 套餐表
create table setmeal(
    id int unsigned primary key auto_increment comment '主键ID',
    name varchar(20) not null unique comment '套餐名称',
    category_id int unsigned not null comment '分类id',
    price decimal(8, 2) not null comment '套餐价格',
    image varchar(300) not null comment '图片',
    description varchar(200) comment '描述信息',
    status tinyint unsigned not null default 0 comment '状态 0:停用 1:启用',
    create_time datetime not null comment '创建时间',
    update_time datetime not null comment '更新时间'
)comment '套餐' ;

-- 套餐菜品关联表
create table setmeal_dish(
    id int unsigned primary key auto_increment comment '主键ID',
    setmeal_id int unsigned not null comment '套餐id ',
    dish_id int unsigned not null comment '菜品id',
    copies tinyint unsigned not null comment '份数'
)comment '套餐菜品中间表';

-- ================================== 导入测试数据 ====================================
-- category
insert into category (id, type, name, sort, status, create_time, update_time) values (1, 1, '酒水饮料', 10, 1, '2022-08-09 22:09:18', '2022-08-09 22:09:18');
insert into category (id, type, name, sort, status, create_time, update_time) values (2, 1, '传统主食', 9, 1, '2022-08-09 22:09:32', '2022-08-09 22:18:53');
insert into category (id, type, name, sort, status, create_time, update_time) values (3, 2, '人气套餐', 12, 1, '2022-08-09 22:11:38', '2022-08-10 11:04:40');
insert into category (id, type, name, sort, status, create_time, update_time) values (4, 2, '商务套餐', 13, 1, '2022-08-09 22:14:10', '2022-08-10 11:04:48');
insert into category (id, type, name, sort, status, create_time, update_time) values (5, 1, '经典川菜', 6, 1, '2022-08-09 22:17:42', '2022-08-09 22:17:42');
insert into category (id, type, name, sort, status, create_time, update_time) values (6, 1, '新鲜时蔬', 7, 1, '2022-08-09 22:18:12', '2022-08-09 22:18:28');
insert into category (id, type, name, sort, status, create_time, update_time) values (7, 1, '汤类', 11, 1, '2022-08-10 10:51:47', '2022-08-10 10:51:47');

-- dish
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (1,'王老吉', 1, 6.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/41bfcacf-7ad4-4927-8b26-df366553a94c.png', '', 1, '2022-06-09 22:40:47', '2022-06-09 22:40:47');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (2,'北冰洋', 1, 4.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/4451d4be-89a2-4939-9c69-3a87151cb979.png', '还是小时候的味道', 1, '2022-06-10 09:18:49', '2022-06-10 09:18:49');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (3,'雪花啤酒', 1, 4.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/bf8cbfc1-04d2-40e8-9826-061ee41ab87c.png', '', 1, '2022-06-10 09:22:54', '2022-06-10 09:22:54');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (4,'米饭', 2, 2.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/76752350-2121-44d2-b477-10791c23a8ec.png', '精选五常大米', 1, '2022-06-10 09:30:17', '2022-06-10 09:30:17');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (5,'馒头', 2, 1.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/475cc599-8661-4899-8f9e-121dd8ef7d02.png', '优质面粉', 1, '2022-06-10 09:34:28', '2022-06-10 09:34:28');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (6,'老坛酸菜鱼', 5, 56.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/4a9cefba-6a74-467e-9fde-6e687ea725d7.png', '原料:汤,草鱼,酸菜', 1, '2022-06-10 09:40:51', '2022-06-10 09:40:51');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (7,'经典酸菜鮰鱼', 5, 66.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/5260ff39-986c-4a97-8850-2ec8c7583efc.png', '原料:酸菜,江团,鮰鱼', 1, '2022-06-10 09:46:02', '2022-06-10 09:46:02');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (8,'蜀味水煮草鱼', 5, 38.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/a6953d5a-4c18-4b30-9319-4926ee77261f.png', '原料:草鱼,汤', 1, '2022-06-10 09:48:37', '2022-06-10 09:48:37');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (9,'清炒小油菜', 6, 18.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/3613d38e-5614-41c2-90ed-ff175bf50716.png', '原料:小油菜', 1, '2022-06-10 09:51:46', '2022-06-10 09:51:46');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (10,'蒜蓉娃娃菜', 6, 18.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/4879ed66-3860-4b28-ba14-306ac025fdec.png', '原料:蒜,娃娃菜', 1, '2022-06-10 09:53:37', '2022-06-10 09:53:37');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (11,'清炒西兰花', 6, 18.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/e9ec4ba4-4b22-4fc8-9be0-4946e6aeb937.png', '原料:西兰花', 1, '2022-06-10 09:55:44', '2022-06-10 09:55:44');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (12,'炝炒圆白菜', 6, 18.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/22f59feb-0d44-430e-a6cd-6a49f27453ca.png', '原料:圆白菜', 1, '2022-06-10 09:58:35', '2022-06-10 09:58:35');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (13,'清蒸鲈鱼', 5, 98.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/c18b5c67-3b71-466c-a75a-e63c6449f21c.png', '原料:鲈鱼', 1, '2022-06-10 10:12:28', '2022-06-10 10:12:28');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (14,'东坡肘子', 5, 138.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/a80a4b8c-c93e-4f43-ac8a-856b0d5cc451.png', '原料:猪肘棒', 1, '2022-06-10 10:24:03', '2022-06-10 10:24:03');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (15,'梅菜扣肉', 5, 58.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/6080b118-e30a-4577-aab4-45042e3f88be.png', '原料:猪肉,梅菜', 1, '2022-06-10 10:26:03', '2022-06-10 10:26:03');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (16,'剁椒鱼头', 5, 66.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/13da832f-ef2c-484d-8370-5934a1045a06.png', '原料:鲢鱼,剁椒', 1, '2022-06-10 10:28:54', '2022-06-10 10:28:54');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (17,'馋嘴牛蛙', 5, 98.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/7a55b845-1f2b-41fa-9486-76d187ee9ee1.png', '配料:鲜活牛蛙,丝瓜,黄豆芽', 1, '2022-06-10 10:37:52', '2022-06-10 10:37:52');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (18,'鸡蛋汤', 7, 4.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/c09a0ee8-9d19-428d-81b9-746221824113.png', '配料:鸡蛋,紫菜', 1, '2022-06-10 10:54:25', '2022-06-10 10:54:25');
insert into dish (id, name, category_id, price, image, description, status, create_time, update_time) values (19,'平菇豆腐汤', 7, 6.00, 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/16d0a3d6-2253-4cfc-9b49-bf7bd9eb2ad2.png', '配料:豆腐,平菇', 1, '2022-06-10 10:55:02', '2022-06-10 10:55:02');

-- setmeal
insert into setmeal (id, category_id, name, price, status, description, image, create_time, update_time) values (1, 4, '商务套餐A', 20.00, 1, '', 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/21a5ed3a-97f6-447a-af9d-53deabfb5661.png', '2022-06-10 10:58:09', '2022-06-10 10:58:09');
insert into setmeal (id, category_id, name, price, status, description, image, create_time, update_time) values (2, 4, '商务套餐B', 22.00, 1, '', 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/8d0075f8-9008-4390-94ca-2ca631440304.png', '2022-06-10 11:00:13', '2022-06-10 11:11:37');
insert into setmeal (id, category_id, name, price, status, description, image, create_time, update_time) values (3, 3, '人气套餐A', 49.00, 1, '', 'https://reggie-itcast.oss-cn-beijing.aliyuncs.com/8979566b-0e17-462b-81d8-8dbace4138f4.png', '2022-06-10 11:11:23', '2022-06-10 11:11:23');

-- setmeal_dish
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (1, 1, 1, 1);
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (2, 1, 4, 1);
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (3, 1, 11, 1);
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (4, 2, 2, 1);
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (5, 2, 4, 1);
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (6, 2, 9, 1);
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (7, 3, 2, 1);
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (8, 3, 6, 1);
insert into setmeal_dish (id, setmeal_id, dish_id, copies) values (9, 3, 5, 1);

-- 1: 查询价格低于 10元 的菜品的名称 、价格 及其 菜品的分类名称
SELECT d.name, d.price , c.name
FROM dish d,category c
WHERE d.category_id = c.id
    AND d.price < 10;

-- 2: 查询所有价格在 10元(含)到50元(含)之间 且 状态为"起售"的菜品名称、价格及其分类名称 (即使菜品没有分类 , 也要将菜品查询出来)
SELECT d.name,d.price,c.name
FROM dish d LEFT JOIN category c
ON d.category_id = c.id
WHERE d.price BETWEEN 10 AND 50;

-- 3: 查询每个分类下最贵的菜品, 展示出分类的名称、最贵的菜品的价格
SELECT c.name , MAX(d.price)
FROM dish d,category c
WHERE d.category_id = c.id
GROUP BY d.category_id;

-- 4: 查询各个分类下 菜品状态为 "起售" , 并且 该分类下菜品总数量大于等于3 的 分类名称
SELECT c.name , COUNT(*) FROM dish d,category c
WHERE d.category_id = c.id
	AND d.status = 1 -- 起售状态
GROUP BY d.category_id
HAVING COUNT(d.category_id) >= 3;

-- 5: 查询出 "商务套餐A" 中包含了哪些菜品 (展示出套餐名称、价格, 包含的菜品名称、价格、份数)
SELECT s.name,s.price,d.name,d.price, sd.copies FROM setmeal s,dish d,setmeal_dish sd
WHERE s.name = '商务套餐A'
	AND sd.setmeal_id = s.id
	AND sd.dish_id = d.id;

-- 6: 查询出低于菜品平均价格的菜品信息 (展示出菜品名称、菜品价格)
SELECT name,price
FROM dish
WHERE price < (SELECT AVG(price));

4、查询结果合并 UNION/UNION ALL

查询结果合并按照笛卡尔积规则
只是union all 就是将两个查询结果合并,不会去重
union 就是将两个查询结果合并,会去重

-- 合并查询
 
SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5
 
SELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3
 
-- union all 就是将两个查询结果合并,不会去重
SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5
UNION ALL
SELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3
 
-- union  就是将两个查询结果合并,会去重
SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5
UNION 
SELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3

你可能感兴趣的:(#,Java基础,java,笔记,mysql)