# DML 语句
# 什么是 DML?
DML:Data Manipulation language
用来操作存储在数据中的数据,常用的 DML 语句有:
- 新增表中的数据:insert into
- 删除表中的数据:delete
- 修改表中的数据:update
- 查询表中的数据:select
# insert 语句
语法如下
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)] -- 列清单
{VALUES | VALUE} (value_list) [, (value_list)] ... -- 值清单
[ON DUPLICATE KEY UPDATE assignment_list] -- 当出现主键或唯一索引冲突事件的行为,比如更新旧数据
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
SET assignment_list
[ON DUPLICATE KEY UPDATE assignment_list]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
SELECT ...
[ON DUPLICATE KEY UPDATE assignment_list]
value:
{expr | DEFAULT}
value_list:
value [, value] ...
assignment:
col_name = value
assignment_list:
assignment [, assignment] ...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 编写 Insert 语句的思路
确认要把数据插入到哪个表中?
确认表的数据库结构,哪些列不能为 NULL,对于不能为 NULL 的列是否有默认值
-- 可以通过命令语句查看表结构 mysql> SHOW CREATE TABLE imc_db.imc_class \G; *************************** 1. row *************************** Table: imc_class Create Table: CREATE TABLE `imc_class` ( `class_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT COMMENT '课程分类ID', `class_name` varchar(10) NOT NULL DEFAULT '' COMMENT '分类名称', `add_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间', PRIMARY KEY (`class_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='课程分类表'
1
2
3
4
5
6
7
8
9
10
11确认对应插入列的插入值的清单
# insert 语句示例
比如下面就指定了一列名称,并往课程分类表中插入了多条数据
INSERT INTO imc_class ( class_name )
VALUES
( 'MySQL' ),
( 'REDIS' ),
( 'MongoDB' ),
( '安全测试' ),
( 'Oracle' ),
( 'SQL Server' ),
( 'Hbase' );
2
3
4
5
6
7
8
9
在创建表的时候,没有为 class_name 添加唯一索引,这里使用上节提到的创建索引语句来增加
CREATE UNIQUE
INDEX uqx_classname ON imc_class ( class_name );
-- 创建 union 的索引,并取名为 uqx_classname ,在 imc_class 的 class_name 列上创建
2
3
唯一索引创建好之后,再执行上述的插入语句就会出现以下的提示错误信息
1062 - Duplicate entry 'MySQL' for key 'uqx_classname', Time: 0.001000s
# ON DUPLICATE KEY UPDATE 示例
由于添加了唯一索引,插入失败,这个时候可以使用 ON DUPLICATE 语句吧 add_time 列的数据修改
INSERT INTO imc_class ( class_name )
VALUES
( 'MySQL' )
ON DUPLICATE KEY UPDATE add_time = CURRENT_TIME;
-- 响应结果是 2 行记录受到了影响,是因为:先删除 MySQL 的值,再更新我们的值
Affected rows: 2, Time: 0.002000s
2
3
4
5
6
7
# select 语句
在 DML 中完成查询的语句是 select 语句,使用很频繁,且为复杂的一个知识点
SELECT -- SELECT 是唯一必选的
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
SQL_NO_CACHE [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...] -- 列或表达式
[FROM table_references
[PARTITION partition_list]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
[HAVING where_condition]
[WINDOW window_name AS (window_spec)
[, window_name AS (window_spec)] ...]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR {UPDATE | SHARE} [OF tbl_name [, tbl_name] ...] [NOWAIT | SKIP LOCKED]
| LOCK IN SHARE MODE]]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- 列或表达式是说:下面这样直接写值,还有一个表达式,就可以执行查询
-- 在该语句下,select 从句就如同打印语句的功能
SELECT 'hello','MySql', 2018+1
查询结果如下:
列:hello MySql 2018+1
值:hello MySql 2019
2
3
4
5
6
7
# where 语句
查询出所有课程中包含 MYSQL 的课程的课程名称
SELECT
title
FROM
imc_db.imc_course
WHERE
title LIKE '%mysql%'
2
3
4
5
6
# 编写简单查询语句的思路
- 确定 FROM 子句:首先确定我们要获取的数据存在哪些表中
- 确定 SELECT 子句:其次是确定我们要取现表中的哪些列
- 确定 WHERE 子句:确认是否需要对表中的数据进行过滤
下面是着重对 select 中能使用的一些知识进行讲解
# MySQL 的比较运算符
= > < >= <= <> !+
:<> 和 -=
都表示不等于BETWEEN min AND max
:列值大于等于最小值,小于等于最大值IS NULL
、IS NOT NULL
:判断列的值是否为 nullLIKE
、NOT LIKE
:%
代表任何数量的字符,_
代表任何一个字符IN
、NOT IN
:判断列的值是否在指定的值列表中
-- 列中是否包含 mysql 关键词
SELECT 'this is mysql course' LIKE '%mysql%';
-- 下划线的用法,这条语句是能查询到的
SELECT 'Mysql' LIKE '_ysql';
-- 如果是这样就不行了,因为只表示任意 一个字符匹配。 前面有好几个字符
SELECT 'xxxMysql' LIKE '_ysql';
2
3
4
5
6
7
8
# 本项目数据库结构和模拟数据
这里提供了所有的项目表和结构和数据备份文件,删除前面创建的表,这里执行下,就可以进行后续的练习使用了
请前往 GitHub 下载该文件
# MySQL 的逻辑运算符
AND、&&
: AND 运算符两边的表达式都为真,返回的结果才为真OR、||
:OR 运算符两边的表达式有一条为真,返回结果就为真XOR
:一真一假时返回真
TIP
任何运算符和 NULL 值运算结果都为 NULL,所以我们之前在定义表的时候,都定位为了非空
-- 需求: 查询出课程标题中包含 MySQL 关键词并且学习人数小于 5000,
-- 课程标题中不包含 MySQL 关键词但学习人数大于 5000 的课程
-- 显示:课程标题和学习人数
-- 方法 1: 编写两条语句,然后使用 UNION ALL 组合起来
SELECT
title,
study_cnt
FROM
imc_db.imc_course
WHERE
title LIKE '%MySQL%'
AND study_cnt < 5000 UNION ALL SELECT title, study_cnt FROM imc_db.imc_course WHERE title NOT LIKE '%MySQL%' AND study_cnt > 5000
-- 方法 2:使用 异或 XOR
SELECT
title,
study_cnt
FROM
imc_db.imc_course
WHERE
title LIKE '%MySQL%'
XOR study_cnt > 5000
-- 别懵逼,记住 一真一假 为真:
-- 也就是说:要么这一条记录 「包含 MySQL 但是学习人数 小于 5000」
-- 要么这一条记录「不包含 MySQL 但是学习人数 大于 500」
-- 这个描述就刚好符合我们的需求
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 从多个表中获取数据 join
前面查询都是单表查询,如何从多表中查询呢? 表与表之间要存在一定的关联关系
如下 3 张表,他们的关系就是都有课程 ID,在逻辑上来说,课程有多个章节,章节有多个小节,这就是关系
课程表:课程 ID
课程章节表:课程 ID
课程小节表:课程 ID、章节 ID
2
3
使用 JOIN 关键字来关联两张表,又分为:
INNER JOIN 内连接:两张表的交集
OUTER JOIN 外连接:又细分为两个
LEFT JOIN 左外连接:
并集:以左边表为主,即使右边变没有匹配的数据,左边的数据都会出来;
补集:还可以通过加 WHERE 子句(判断 B 表中必有值的数据为 null),查询只存在 A 表中,而不存在 B 表中的数据,如下面的练习,查询没有任何章节的课程
RIGHT JOIN 右外连接:与左外链接相反
-- 内连接练习:查询每一门课程的 课程 ID、课程名称和章节名称
SELECT
a.course_id,
a.title,
b.chapter_name
FROM
imc_course a
JOIN imc_chapter b ON b.course_id = a.course_id
-- 使用 join 关联两个表,使用 ON 来声明两个表中的关联关系
-- 新增一条课程数据
INSERT INTO `imc_db`.`imc_course`(`title`, `title_desc`, `type_id`, `class_id`, `level_id`, `online_time`, `study_cnt`, `course_time`, `intro`, `info`, `harvest`, `user_id`, `main_pic`, `content_score`, `level_score`, `logic_score`, `score`) VALUES ('关联测试', '关联测试', 10, 5, 1, '2020-04-20 07:26:23', 0, '00:00:00', '', '', '', 0, '', 0.0, 0.0, 0.0, 0.0);
-- 使用上面的内连接查询新插入的数据,会发现没有结果出来
SELECT
a.course_id,
a.title,
b.chapter_name
FROM
imc_course a
JOIN imc_chapter b ON b.course_id = a.course_id
WHERE a.title = '关联测试'
-- 可以使用外链接来查询到,即使该课程没有任何章节
SELECT
a.course_id,
a.title,
b.chapter_name
FROM
imc_course a
LEFT JOIN imc_chapter b ON b.course_id = a.course_id
WHERE a.title = '关联测试'
-- 左外连接还有一个查询技巧:就是查询没有任何章节的课程
-- 上面演示的 SQL 由于我知道这条数据没有章节,如果去掉就会显示还包含有章节的课程了
-- 这里只要加上 where 条件,判定章节中的必有字段为 null 即可
SELECT
a.course_id,
a.title,
b.chapter_name
FROM
imc_course a
LEFT JOIN imc_chapter b ON b.course_id = a.course_id
WHERE b.course_id IS NULL
-- 响应的结果
course_id | title | chapter_name
101 | 关联测试 | null
-- 此种方式,比使用 not in(子查询) 来达成,性能要好
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# group by 、having 分组语句
GROUP BY...HAVING 子句的作用:
- 把结果集按某些列分成不同的组,并对分组后的数据进行聚合操作
- 可以通过 having 对分组后的数据进行过滤,where 语句只能用在分组前
--范例 1: 查询每个难度的课程有多少门课程
SELECT
b.level_name, -- 分组键可以出现在 select 语句中,非分组键则不能
count( * ) -- 还可以包含一个或多个聚合函数
FROM
imc_course a
JOIN imc_level b ON a.level_id = b.level_id
GROUP BY
b.level_name
-- 查询响应数据
level_name count( * )
入门 22
初级 28
高级 24
中级 27
-- 如果非分组列出现在了 select 中则会出现 sql_mode=only_full_group_by 类似的错误信息
-- 这是因为 group by 的使用时受 sql_mode 的影响,可以查看当前的 sql_mode 值
SHOW VARIABLES LIKE 'sql_mode'
-- 从响应的数据中可以看到:的确有 ONLY_FULL_GROUP_BY 的配置
Variable_name Value
sql_mode ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
对分组后的语句进行过滤
-- 统计每个分类下课程大于 3 门的难度有哪些
SELECT
b.class_name,
c.level_name,
count( * )
FROM
imc_course a
JOIN imc_class b ON b.class_id = a.class_id
JOIN imc_level c ON c.level_id = a.level_id
GROUP BY
b.class_name,
c.level_name
HAVING
count( * ) > 3 -- 在分组后,进行过滤
-- 响应数据
class_name level_name count( * )
Hbase 初级 4
Oracle 初级 4
Hbase 高级 5
运维 高级 4
MySQL 高级 4
Redis 初级 4
MongoDB 入门 4
HadoopDock 中级 4
Docker 中级 4
运维 中级 4
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 常用的聚合函数
count(*)
、count(col)
:统计函数*
表示的这一行数据,也可以选择具体的列,因为有些列有值或则没有值,和具体的聚合函数的用途有关sum(col_name)
:累加函数计算表中符合条件的数值列的合计值,此列需要是数值类型
avg(cole_name)
:平均计算表中符合条件的数值列的平均值(就是 sum/count)
MAX(cole_name)
:计算表中符合条件的任意列中数据的最大值MIN(cole_name)
:计算表中符合条件的任意列中数据的最小值
# count 统计范例
-- 统计函数 范例:统计课程表的总课程数量 与 课程中老师的数量
SELECT
count( course_id ), -- 统计课程 ID,就是课程数量
count( DISTINCT user_id ) -- 统计该课程老师数量,因为一个老师可以负责多个课程,需要去重
FROM
imc_course
-- 响应数据
count( course_id ) count( DISTINCT user_id )
101 6
2
3
4
5
6
7
8
9
10
# avg 范例
-- 一个复杂点的 sql:利用课程评价表中的评分,更新课程表中的课程的评分
-- 课程评价表中的数据是每个用户对课程的评分
-- 课程表中的评分是需要 课程评价表中的评分的平均值,作为一个综合评分
对于复杂的语句,我们需要分段来写 sql,先实现一段,再继续另一端,再合并起来,这里还没有学习更新语句,后半段就先留着后续来补充
-- 查询:统计每门课程的平均分
SELECT
course_id,
avg( content_score ) AS content_score,
avg( level_score ) AS level_score,
avg( logic_score ) AS logic_score,
avg( score ) AS avg_score
FROM
imc_classvalue
GROUP BY
course_id
-- 响应数据
course_id content_score level_score logic_score avg_score
8 8.98000 9.14000 8.58000 0.00000
17 9.10000 9.10000 9.45000 0.00000
59 8.85000 8.90000 8.82500 0.00000
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# max 范例
-- 查询出学习人数最多的课程
SELECT
title
FROM
imc_course
WHERE
study_cnt = ( SELECT MAX( study_cnt ) FROM imc_course )
-- 需要分两步查询出来
-- 第一步:先查询出来人数最多的列,就是这个字查询,会显示出人数
-- 第二步:以该人数为条件,查询出对应的课程信息
2
3
4
5
6
7
8
9
10
# order by 排序
每个存储引擎默认的排序方式是不同的,InnoDB 默认是使用主键的顺序进行排序。那么使用 order by 子句是对查询结果进行排序的最安全的方法。
列名后增加 ASC 升序排列,DESC 降序排列
如 order by id desc
order by 子句也可以使用 select 子句中未出现的 列 或是 函数
-- 查询出每门课程的学习人数,并按学习人数从高到底排列
SELECT
title,
study_cnt
FROM
imc_course
ORDER BY
study_cnt DESC
-- ORDER BY 2 DESC 还可以使用 slect 列 的位置来引用排序
-- 响应数据
title study_cnt
PostgreSQL课程-64209 9939
SQLServer课程-68633 9731
MySQL课程-86475 9716
PostgreSQL课程-33460 9588
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Limit 限制返回结果集行数
常用语数据列表分页,一定要和 order by 子句配合使用,是因为:由于分页过程中每次分页查询都会重复的执行查询语句,所以要保证排序顺序是一样的,否则就可能出现错误的数据
语法:limit 起始偏移量,结果集的行数
SELECT
course_id,
title
FROM
imc_course
ORDER BY study_cnt DESC
LIMIT 0,10 -- 起始数据从 0 开始,返回 10 行数据
-- 如果是第 2 页的数据,则是 limit 10,10
2
3
4
5
6
7
8
# 创建视图 create view
视图中不存储数据
CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = user]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement -- 我们熟悉的查询语句
[WITH [CASCADED | LOCAL] CHECK OPTION]
2
3
4
5
6
7
8
-- 定义一个包含课程 ID、课程名称、课程分类、课程方向以及课程难度的视图
-- 第一步:先写出这些数据的查询语句
SELECT
a.course_id,
a.title,
b.class_name,
c.type_name,
d.level_name
FROM
imc_course a
JOIN imc_class b ON b.class_id = a.class_id
JOIN imc_type c ON c.type_id = a.type_id
JOIN imc_level d ON d.level_id = a.level_id
-- 响应数据
course_id title class_name type_name level_name
1 MySQL课程-79889 大数据 算法&数学 入门
2 MySQL课程-69546 Hbase 云计算&大数据 初级
3 PostgreSQL课程-43917 大数据 前端开发 高级
...
-- 定义视图,取名 vm_course
CREATE VIEW vm_course AS
SELECT
a.course_id,
a.title,
b.class_name,
c.type_name,
d.level_name
FROM
imc_course a
JOIN imc_class b ON b.class_id = a.class_id
JOIN imc_type c ON c.type_id = a.type_id
JOIN imc_level d ON d.level_id = a.level_id
-- 查询视图
SELECT * FROM vm_course
-- 可以看到,视图就类似一章虚拟表,把我们编写的 sql 语句保存起来了的感觉
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# delete 按条件删除数据
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
2
3
4
5
删除语法中也有 where 等语句,与 select 中的效果类似
-- 范例 1:删除课程表中没有章节信息的课程
-- 第一步:先写出没有章节信息的课程信息
SELECT
*
FROM
imc_course a
LEFT JOIN imc_chapter b ON a.course_id = b.course_id
WHERE
b.course_id IS NULL
-- 第二步:使用 delete 语法
DELETE a -- 删除哪个表中的数据,因为下面关联了两张表
FROM
imc_course a
LEFT JOIN imc_chapter b ON a.course_id = b.course_id
WHERE
b.course_id IS NULL
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 范例 2:删除课程方向表中重复的课程方向,并保留方向 ID 最小的一条,并在方向名称上增加唯一索引
-- 01. 首先查看 方向表 的结构
SHOW CREATE TABLE imc_type;
-- 响应的结构
CREATE TABLE `imc_type` (
`type_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT COMMENT '课程方向ID',
`type_name` varchar(10) NOT NULL DEFAULT '' COMMENT '课程方向名称',
`add_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '填加时间',
PRIMARY KEY (`type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='课程方向表'
-- 可以看到 type_name 上没有唯一索引,所以会导致重复的数据进入
-- 02. 先查看下有哪些数据是重复的(注意,前面给出的数据表,里面没有重复的数据,需要自己手动新增几条)
SELECT
type_name,
count( * )
FROM
imc_type
GROUP BY
type_name
HAVING
count( * ) > 1
-- 03. 找出保留 id 最小的数据
SELECT
type_name,
count( * ),
min( type_id ) AS min_type_id -- 由于分组后相同的只会出现一条数据,直接追加最小值就是正确的
FROM
imc_type
GROUP BY
type_name
HAVING
count( * ) > 1
-- 响应的数据
type_name count( * ) min_type_id
数据库 2 8
游戏 2 10
-- 04. 找出要删除的数据,使用子查询
SELECT
*
FROM
imc_type AS a
JOIN ( SELECT type_name, count( * ), min( type_id ) AS min_type_id FROM imc_type GROUP BY type_name HAVING count( * ) > 1 ) AS b ON a.type_name = b.type_name
AND a.type_id > b.min_type_id
-- 响应的数据,可以看到查询出来的都是比 min_type_id 大的数据
type_id type_name add_time type_name(1) count( * ) min_type_id
11 游戏 2020-04-20 10:39:12 游戏 2 10
12 数据库 2020-04-20 10:39:36 数据库 2 8
-- 05. 最终形成的删除数据
DELETE a
FROM
imc_type AS a
JOIN ( SELECT type_name, count( * ), min( type_id ) AS min_type_id FROM imc_type GROUP BY type_name HAVING count( * ) > 1 ) AS b ON a.type_name = b.type_name
AND a.type_id > b.min_type_id
-- 06. 创建唯一索引
CREATE UNIQUE INDEX uqx_typename ON imc_type(type_name)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# update 修改语句
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET assignment_list
[WHERE where_condition] -- 过滤出需要修改的数据
[ORDER BY ...]
[LIMIT row_count]
value:
{expr | DEFAULT}
assignment:
col_name = value
assignment_list:
assignment [, assignment] ...
2
3
4
5
6
7
8
9
10
11
12
13
14
对于 order by 和 limit 的参数一般不常用,但是可以用在大批量更新的场景:比如要更新 10 万行数据,如果一次性全部更新,可能会导致主从复制延迟的问题,所以可以采用他们来实现一定顺序的分页更新,每次只更新一万行
# 编写 update 语句的思路:
确定要更新的数据存储在哪张表中?:update 子句
通常可以先写出一个 select 语句,查找出来要修改的数据,然后再修改为 update 语句
确定要更新的列与值:set 语句
确认更新数据的条件:where 语句
# 常用更新语句示例
范例 1:冻结用户的账户:冻结昵称为 沙占 的用户
-- 先写查询语句
SELECT
user_nick,
user_status
FROM
imc_user
WHERE
user_nick = '沙占'
-- 改写成 update 语句
UPDATE imc_user
SET user_status = 0
WHERE
user_nick = '沙占'
2
3
4
5
6
7
8
9
10
11
12
13
14
范例 2:随机推荐 10 门课程
-- 给该表新增一列,是否推荐的列,由于真实的推荐是一个很复杂的计算的出来的结果,这里简单的模拟下
-- 使用修改表的语句 alter 来新增一列
ALTER TABLE imc_course ADD is_recommand TINYINT DEFAULT 0 COMMENT '是否推荐,0 不推荐,1 推荐';
-- 随机查询出 10 条语句
SELECT
course_id
FROM
imc_course
ORDER BY RAND( ) -- 使用了 rand 函数来排序
LIMIT 10
-- 改写成 update 语句
UPDATE imc_course
SET is_recommand = 1
ORDER BY
RAND( )
LIMIT 10;
-- 查询刚刚推荐的数据
SELECT course_id,title from imc_course WHERE is_recommand = 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
范例 3:完成 前面 svg 里面剩下的 sql 作业,更新
-- 一个复杂点的 sql:利用课程评价表中的评分,更新课程表中的课程的评分
-- 课程评价表中的数据是每个用户对课程的评分
-- 课程表中的评分是需要 课程评价表中的评分的平均值,作为一个综合评分
-- 查询:统计每门课程的平均分
SELECT
course_id,
avg( content_score ) AS content_score,
avg( level_score ) AS level_score,
avg( logic_score ) AS logic_score,
avg( score ) AS avg_score
FROM
imc_classvalue
GROUP BY
course_id
-- 改成更新语句
UPDATE imc_course a
JOIN (
SELECT
course_id,
avg( content_score ) AS content_score,
avg( level_score ) AS level_score,
avg( logic_score ) AS logic_score,
avg( score ) AS avg_score
FROM
imc_classvalue
GROUP BY
course_id
) b ON a.course_id = b.course_id
SET a.content_score = b.content_score,
a.level_score = b.level_score,
a.logic_score = b.logic_score,
a.score = avg_score
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34