1.聚合函数

在 MySQL 中,聚合函数用于对一组数据进行计算并返回单个结果,通常与 GROUP BY 子句配合使用(也可单独使用,对全表数据聚合)。常用的聚合函数包括 COUNT()SUM()AVG()MAX()MIN()

1.1 COUNT(): 统计记录数量

用于计算符合条件的记录行数,有三种常见用法:

  • COUNT(*): 统计所有记录(包括 NULL 值)
-- 统计 students 表的总人数
select count(*) as 总人数 from students;
  • COUNT(字段名): 统计指定字段非 NULL 值的记录数
-- 统计身高(height)不为 NULL 的学生数量
select count(height) as 身高非空人数 from students;
  • COUNT(DISTINCT 字段名): 统计指定字段非重复且非 NULL 的记录数
-- 统计不重复的姓名数量
select count(distinct name) as 不重复姓名数 from students;

1.2 SUM(): 计算数值总和

用于计算指定数值字段的总和(忽略 NULL 值)。

-- 计算所有学生的年龄总和
select sum(age) as 年龄总和 from students;

-- 计算身高大于1.70的学生身高总和
select sum(height) from students where height > 1.7;

1.3 AVG(): 计算平均值

用于计算指定数值字段的平均值(忽略 NULL 值)。

-- 计算所有学生的平均年龄
select avg(age) as 平均年龄 from students;

-- 计算身高非 NULL 的学生平均身高
select avg(age) from students;

1.4 MAX(): 获取最大值

用于获取指定字段的最大值(忽略 NULL 值)。

-- 查找年龄最大的学生年龄
select max(age) as 最大年龄 from students;

-- 查找身高最高的学生身高
select max(height) as 最高身高 from students;

1.5 MIN(): 获取最小值

用于获取指定字段的最小值(忽略 NULL 值)。

-- 查找年龄最小的学生年龄
select min(age) as 最小年龄 from students;

-- 查找身高最矮的学生身高
select min(height) AS 最矮身高 from students;

1.6 聚合函数与 GROUP BY 结合

当需要按某个字段分组聚合时,使用 GROUP BY 子句,聚合函数会对每个分组单独计算结果。

-- 按性别分组,统计每组的人数、平均年龄、最大身高
select gender,count(*) as 人数,avg(age) as 平均年龄,max(height) as 最高身高 from students group by gender;

1.7 小结

  • 聚合函数会自动忽略NULL值,(COUNT(*) 除外,它统计所有记录)

  • GROUP BY 子句必须放在 WHERE 之后、ORDER BY 之前。

  • 若使用 GROUP BY,SELECT 后只能出现聚合函数或 **GROUP BY 中指定的分组字段 **。

  • 可通过 HAVING 子句对聚合结果进行筛选(类似 WHERE,但 HAVING 用于聚合后过滤):

-- 筛选出人数大于2的性别分组
mysql> select gender,count(*) as 人数, avg(age) as 平均年龄, max(height) as 最高身高 from students group by gender having 人数 > =2;

2.分组查询

在 MySQL 中,分组查询通过 GROUP BY 子句实现,用于将表中的数据按照指定字段的值进行分组,相同值的记录会被归为一组,然后可以对每个组进行聚合计算(如统计数量、求平均值等)。分组查询通常与聚合函数(COUNTSUMAVG 等)配合使用,适合对数据进行分类汇总分析。

基本语法:

SELECT 分组字段, 聚合函数(字段)
FROM 表名
[WHERE 条件]  -- 分组前筛选数据
GROUP BY 分组字段  -- 按指定字段分组
[HAVING 聚合条件]  -- 分组后筛选聚合结果
[ORDER BY 排序字段];  -- 对分组结果排序

2.1: 简单分组(按单个字段分组)

-- 按 gender(性别)分组,统计每个性别的学生数量:
select gender,count(*) as 人数 from students group by gender;
  • 分组后,SELECT 后只能出现分组字段聚合函数,不能出现其他字段(如 nameage 等非分组字段)。

2.2 多字段分组(按多个字段组合分组)

当单个字段无法满足分组需求时,可以按多个字段组合分组(只有多个字段值完全相同时才会被归为一组)。

-- 按 gender(性别) 和 age(年龄) 分组, 统计每个组合的学生数量:
select gender,age,count(*) as 人数 from students group by gender,age;

2.3: 分组前筛选(WHERE 子句)

先通过 WHERE 筛选出符合条件的记录,再对筛选后的结果进行分组。

-- 筛选出 age > 16 的学生,再按 gender 分组统计人数:
select gender,count(*) as 人数 from students where age > 16 group by gender;

2.4: 分组后筛选(HAVING 子句)

HAVING 子句用于对分组后的结果进行筛选(针对聚合函数的结果),类似 WHERE,但 WHERE 作用于分组前,HAVING 作用于分组后。

-- 按 gender 分组,筛选出 “人数> 2” 的组:
select gender,count(*) as 人数 from students group by gender having 人数 > 2;

2.5 分组 + 排序

对分组后的结果按聚合字段排序,使结果更易读。

-- 按 gender 分组,统计每组的平均年龄,并按平均年龄降序排序:
select gender,count(*) as 人数,avg(age) as 平均年龄 from students group by gender order by 平均年龄 desc;

2.6小结

  • GROUP BY 的位置: 必须放在 WHERE 之后、HAVINGORDER BY 之前。

  • SELECT 字段限制: GROUP BY 分组后, SELECT 后只能出现分组字段聚合函数,否则会报错或返回不可预期的结果。

  • NULL 值的处理: GROUP BY 会将所有 NULL 值视为相同的分组(如示例 1 中 gender=NULL 的记录被归为一组)。

  • WHEREHAVING 的区别:

    • WHERE: 分组前筛选,不能使用聚合函数(如 WHERE COUNT(*) > 2 是错误的)。
    • HAVING: 分组后筛选,可使用聚合函数(如 HAVING COUNT(*) > 2 是正确的)。

3.连接查询方式

3.1 内连接查询

内连接(INNER JOIN) 是 MYSQL中最常用的连接方式,用于获取两个表中满足连接条件的交集数据(即只返回两个表中匹配成功的记录)

内连接的基本语法:

SELECT 字段列表
FROM 表1
INNER JOIN 表2 
ON 表1.关联字段 = 表2.关联字段;

演示用表创建:

我们创建两个相关联的表: students(学生表)和 classes(班级表),通过 class_id 字段关联。

-- 创建班级表
CREATE TABLE classes (
  id INT PRIMARY KEY AUTO_INCREMENT,
  class_name VARCHAR(50) NOT NULL,
  teacher VARCHAR(30) NOT NULL
);

-- 创建学生表(包含班级关联字段class_id)
CREATE TABLE students (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(30) NOT NULL,
  age INT,
  class_id INT,
  -- 外键关联班级表的id字段
  FOREIGN KEY (class_id) REFERENCES classes(id)
);

-- 向班级表插入数据
INSERT INTO classes (class_name, teacher) VALUES
('高一(1)班', '王老师'),
('高一(2)班', '李老师'),
('高一(3)班', '张老师');

-- 向学生表插入数据(包含关联的class_id)
INSERT INTO students (name, age, class_id) VALUES
('张三', 16, 1),
('李四', 17, 1),
('王五', 16, 2),
('赵六', 17, 2),
('孙七', 16, 3),
('周八', 17, NULL); -- 周八没有班级(class_id为NULL,不会被内连接查询到)

内连接查询示例:

-- 示例 1:查询学生及其所属班级信息
mysql> select s.id as 学生id,s.name as 学生姓名,c.class_name as 班级名称,c.teacher as 班主任 from students s inner join classes c on s.class_id = c.id;

image-20250911151159989

-- 示例 2: 查询高一 (2) 班的学生信息
select s.id 学生id,s.name 学生姓名,c.class_name 班级名称,c.teacher 班主任 from students s join classes c on s.class_id = c.id where c.class_name='高一(2)班';

image-20250911151719976

内连接的特点:

  • 只返回两个表中满足条件的记录(交集)
  • 可以使用表别名(如 s 代表 students,c 代表 classes)简化查询
  • 连接条件通过 ON 子句指定,必须包含两个表的关联字段
  • 可以结合 WHEREORDER BY 等子句进行进一步筛选和排序

3.2 左连接查询

左连接(LEFT JOIN 或 LEFT OUTER JOIN)是 MySQL 中常用的表连接方式,用于查询左表(JOIN 关键字左侧的表)的所有记录,以及右表中与左表满足连接条件的匹配记录。若右表无匹配记录,会用 NULL 填充右表的字段。

左连接基本语法:

SELECT 字段列表
FROM 左表
LEFT JOIN 右表 
ON 连接条件;
  • ON 后指定连接条件(如两表的关联字段匹配关系)
-- 左连接查询所有学生及其对应的班级信息

select s.id 学生id,s.name 学生姓名,c.class_name 班级名称,c.teacher 班主任 from students s left join classes c on s.class_id = c.id;

image-20250912080014683

特点:

  • 左表数据全保留: 无论右表是否有匹配记录,左表的所有行都会出现在结果中。
  • 右表缺省用 NULL 填充: 若右表无满足连接条件的记录,右表字段显示为 NULL。
  • 与内连接的区别: 内连接(JOIN)只保留两表匹配的记录,而左连接强制保留左表全部数据,适合需 "包含左表所有数据" 的场景(如查询所有学生,无论是否有班级)。

3.3 右连接查询

右连接(RIGHT JOIN)与左连接逻辑相反,它会返回右表(JOIN 关键字右侧的表)的所有记录,以及左表中与右表满足连接条件的匹配记录。若左表无匹配记录,会用 NULL 填充左表的字段。

基本语法:

SELECT 字段列表
FROM 左表
RIGHT JOIN 右表 
ON 连接条件;
  • 核心是保证右表的所有记录都被保留,左表仅显示匹配项。
-- 假设我们新增一个没有学生的班级:
INSERT INTO classes (class_name, teacher) VALUES ('高一(4)班', '刘老师');

-- 执行右连接查询:
mysql> SELECT c.id AS 班级ID,c.class_name AS 班级名称,s.name AS 学生姓名,s.age AS 学生年龄 FROM students s RIGHT JOIN classes c ON s.class_id = c.id;

image-20250912081404429

特点:

  • 右表数据全保留: 无论左表是否有匹配记录,右表的所有行都会出现在结果中。
  • 左表缺省用 NULL 填充: 若左表无满足连接条件的记录,左表字段显示为 NULL。
  • 适用场景: 适合需要 "以右表为基准,关联查询左表数据" 的场景,例如 "查询所有班级及其学生信息,包括没有学生的班级"。
  • 与左连接的转换: 右连接可通过交换表的位置转换为左连接(如 A RIGHT JOIN B 等价于 B LEFT JOIN A),实际使用中左连接更常用。

3.4 自连接查询

自连接(Self Join)是一种特殊的表连接方式,指同一张表与自身进行连接,通过给表起不同的别名,将一张表虚拟成两张 “不同” 的表来处理,从而实现对表中数据的关联查询(如查询同一表中具有层级关系、关联关系的数据)。

例如在学生表中,若存在 “班长” 与 “普通学生” 的层级关系(可通过monitor_id字段关联班长的id),就可以用自连接查询每个学生及其对应的班长信息。

基本语法:

SELECT 字段列表
FROM 表名 别名1
JOIN 表名 别名2  -- 同一张表用不同别名
ON 别名1.关联字段 = 别名2.关联字段;  -- 连接条件(表内字段的关联关系)
  • 核心是通过别名区分 “两张虚拟表”(实际为同一张表)
  • 可结合INNER JOINLEFT JOIN等连接类型使用

示例:

假设我们扩展students表,增加monitor_id字段表示该学生的班长 ID(关联自身的id):

-- 扩展表结构
ALTER TABLE students ADD COLUMN monitor_id INT;

-- 更新数据(假设张三、赵六是班长,monitor_id为NULL表示自己是班长)
UPDATE students SET monitor_id = 1 WHERE id IN (2,3);  -- 李四、王五的班长是张三(id=1)
UPDATE students SET monitor_id = 4 WHERE id = 5;       -- 孙七的班长是赵六(id=4)

-- 用自连接查询 “学生及其对应班长姓名”:
mysql> select s.id 学生id, s.name 学生姓名, m.monitor_id 班长id, m.name 班长姓名 from students s left join students m on s.monitor_id = m.id;

image-20250912100207302

3.5 子查询

子查询(Subquery)是指嵌套在另一个 SQL 查询中的查询语句,也称为内层查询。外层查询可以使用子查询的结果作为条件、数据源或计算依据,实现更复杂的查询逻辑。

基本语法:

子查询的基本结构是将一个查询语句放在另一个查询的WHEREFROMSELECT子句中:

-- 外层查询使用子查询的结果作为条件
SELECT 字段列表
FROM 表名
WHERE 字段 运算符 (
  SELECT 字段列表  -- 子查询(内层查询)
  FROM 表名
  WHERE 条件
);
  • 子查询需用括号()包裹
  • 可返回单个值、多个值或多行多列数据,根据返回结果类型适配外层查询的运算符(如=INEXISTS等)

示例:

-- 子查询返回单个值(用于比较)
-- 查询年龄大于所有学生平均年龄的学生

select name,age from students where age > (select avg(age) from students);

image-20250912101903306

-- 子查询返回多个值(用IN匹配)
-- 查询“高一(1)班”的所有学生

mysql> select * from students where class_id in (select id from classes where class_name = '高一(1)班');

image-20250912102318313

-- 子查询作为数据源(用FROM子句)
-- 查询每个班级的学生人数(子查询作为临时表)

select c.class_name 班级名字,ifnull(temp.student_count, 0) 学生数量 from classes c left join(select class_id,count(*) as student_count from students group by class_id) temp on c.id = temp.class_id;

image-20250912105134047

-- 用EXISTS判断子查询是否有结果
-- 查询有学生的班级

mysql> select class_name from classes c where exists(select 1 from students s where s.class_id = c.id);

4.数据库设计之三范式

在 MySQL 数据库设计中,三大范式(Normal Forms, NF) 是指导数据表结构优化的核心原则,其目标是减少数据冗余、避免更新异常(插入 / 删除 / 修改异常),确保数据的一致性和完整性。三大范式从低到高逐步严格,通常满足第三范式即可应对绝大多数业务场景,更高阶的范式(如 BCNF、4NF)则适用于特殊复杂场景。

**函数依赖: **

在理解范式前,需先掌握函数依赖: 设数据表中的两个属性集 A 和 B,若对于 A 中的每一个值,B 中都有唯一确定的值与之对应,则称 “A 函数决定 B” 或 “B 函数依赖于 A”,记为 A → B

  • 例:在学生表中,“学号” 唯一确定 “姓名” 和 “班级”,即 学号 → 姓名学号 → 班级
  • 关键术语:
    • 主键(候选键): 能唯一决定表中所有其他属性的属性集(如上例中的 “学号”)。
    • 非主属性: 除主键外的其他属性(如上例中的 “姓名”“班级”)。

4.1 第一范式(1NF): 原子性原则

定义: 数据表中的每一列(属性)必须是不可再分的原子值,即列不能包含多个子属性或复合值。
1NF 是数据库设计的最低要求,不满足 1NF 的结构甚至不能称为 “关系型数据表”。

反例(不满足 1NF)

假设设计学生信息表如下,其中 “联系方式” 列包含 “电话” 和 “邮箱” 两个子属性,不符合原子性:

学号 姓名 联系方式
2024001 张三 13800138000, zhang@xxx.com
2024002 李四 13900139000, li@xxx.com

正例(满足 1NF)

将 “联系方式” 拆分为独立的 “电话” 和 “邮箱” 列,确保每列值不可再分:

学号 姓名 电话 邮箱
2024001 张三 13800138000 zhang@xxx.com
2024002 李四 13900139000 li@xxx.com

4. 2第二范式(2NF): 消除部分依赖

前提: 必须先满足第一范式(1NF)。

定义:数据表中的每一个非主属性, 必须完全函数依赖于主键(而非依赖主键的某一部分,即 “部分依赖”)。

2NF 主要解决 “复合主键” 场景下的冗余问题 —— 若主键由多个属性组成(如选课表的主键为 “学号 + 课程号”),非主属性不能仅依赖主键中的某一个属性。

反例(不满足 2NF)

设计选课表,主键为 “学号 + 课程号”,但 “学生姓名” 仅依赖 “学号”,“课程名称” 仅依赖 “课程号”(存在部分依赖):

学号 课程号 学生姓名 课程名称 成绩
2024001 C001 张三 数学 90
2024001 C002 张三 英语 85
2024002 C001 李四 数学 88

正例(满足 2NF)

拆分表为 3 个独立表,消除部分依赖:

  • 学生表(主键: 学号): 存储学生基本信息
学号 学生姓名
2024001 张三
2024002 李四
  • 课程表(主键:课程号):存储课程基本信息
课程号 课程名称
C001 数学
C002 英语
  • 选课表(主键:学号 + 课程号): 仅存储选课关系和成绩(非主属性 “成绩” 完全依赖复合主键)
学号 课程号 成绩
2024001 C001 90
2024001 C002 85
2024002 C001 88

4.3 第三范式(3NF): 消除传递依赖

前提: 必须先满足第二范式(2NF)。

定义: 数据表中的每一个非主属性, 必须不传递依赖于主键(即非主属性之间不能存在 “非主属性 A → 非主属性 B” 的依赖关系)。

3NF解决 “非主属性通过其他非主属性间接依赖主键” 的问题,进一步减少冗余。

反例(不满足 3NF)

设计学生表,主键为 “学号”,但 “班级辅导员” 依赖 “班级”,“班级” 依赖 “学号”(存在传递依赖:学号 → 班级 → 班级辅导员):

学号 学生姓名 班级 班级辅导员
2024001 张三 一班 王老师
2024002 李四 一班 王老师
2024003 王五 二班 李老师

正例(满足 3NF)

拆分表为 2 个独立表,消除传递依赖:

1.学生表(主键: 学号):仅存储学生与班级的直接关联

学号 学生姓名 班级
2024001 张三 一班
2024002 李四 一班
2024003 王五 二班

2.班级表(主键:班级): 存储班级与辅导员的关联

班级 班级辅导员
一班 王老师
二班 李老师

小结:

范式 核心要求(前提: 满足前一范式) 解决的问题 关键目标
1NF 列值原子化(不可再分) 非关系型结构问题 确保数据表合法性
2NF 非主属性完全依赖主键 部分依赖导致的冗余 消除部分依赖
3NF 非主属性不传递依赖主键 传递依赖导致的冗余 消除传递依赖

4.4 E-R模型的介绍

E-R模型主要由三个要素构成: 实体(Entity)属性(Attribute)关系(Relationship),通过 E-R 图(实体 - 关系图)直观呈现。

E-R模型的效果图:

image-20250912130505490

E-R 图表示:

  • 矩形表示实体,矩形内标注实体名称(如 “班级”、“学生”)。
  • 椭圆形表示属性,通过连线与对应实体关联,椭圆内标注属性名称(如 “班级号”、“班级名”)。
  • 菱形表示关系,菱形内标注关系名称(如 “选课”、“组成”),通过连线与关联的实体连接,并在连线上标注关系的基数(如 1:1、1:N、M:N)。
    • 1:1 关系: 通常将一个实体的主键作为另一个表的外键。
    • 1:N 关系:在 “多” 的一方表中加入 “一” 方的主键作为外键(如 “学生表” 中加入 “班级号” 作为外键关联 “班级表”)。
    • M:N 关系: 需新增一个 “中间表”,存储两个实体的主键作为联合主键(或外键),并可包含关系的属性(如 “选课表” 包含 “学号”“课程号” 外键,及 “成绩” 属性)。

5.外键约束写详解

5.1 外键约束的作用

外键约束式MySQL中用于维护表与表之间关联关系的重要机制,主要作用包括:

  • 保证数据完整性: 确保子表中引用的数据在父表中一定存在
  • 维护数据一致性: 当父表中的数据发生变化时,可通过设置不同的外键动作(如级联删除、级联更新等) 自动维护子表的数据

5.2 为已存在的字段添加外键约束

当需要为已存在的表添加外键约束时,可使用 ALTER TABLE 语句,语法如下:

ALTER TABLE 子表名
ADD CONSTRAINT 外键约束名
FOREIGN KEY (子表外键字段名)
REFERENCES 父表名(父表被引用字段名)
[ON DELETE 动作]
[ON UPDATE 动作];

假设已存在 classes 表(父表)和 students 表(子表),现在为 students 表的 class_id 字段添加外键约束:

mysql> alter table students
    -> add constraint fk_students_classes
    -> foreign key (class_id)
    -> references classes(id)
    -> ;

image-20250914194309987

  • 添加外键前,确保子表中已存在的外键字段值在父表中都能找到对应的值
  • 子表外键字段与父表被引用字段的数据类型必须完全一致
  • 父表被引用字段必须是主键或唯一索引

5.3 在创建数据表时设置外键约束

在创建数据表时设置外键语法:

CREATE TABLE 子表名 (
    字段1 数据类型 [约束],
    字段2 数据类型 [约束],
    ...,
    [CONSTRAINT 外键约束名]
    FOREIGN KEY (子表外键字段名)
    REFERENCES 父表名(父表被引用字段名)
    [ON DELETE 动作]
    [ON UPDATE 动作]
);

创建子表 head_teacher 并同时设置外键约束

mysql> create table head_teacher(
    -> id int primary key auto_increment,
    -> name varchar(20) not null,
    -> c_id int not null,
    -> constraint fk_head_teacher_classes
    -> foreign key (c_id)
    -> references classes(id)
    -> );

5.4 删除外键约束

删除外键约束需使用外键约束名,语法如下:

ALTER TABLE 子表名
DROP FOREIGN KEY 外键约束名;

示例

删除 students 表中的 fk_students_classes 外键约束:

ALTER TABLE students DROP FOREIGN KEY fk_students_classes;

5.5 小结

  • 外键约束的核心作用是保证数据的引用完整性,防止出现无效的关联数据。
  • 可为已存在的表添加外键约束,使用 ALTER TABLE ... ADD CONSTRAINT 语句。
  • 可在创建表时直接定义外键约束,明确表间关系。
  • 外键动作明确了当父表中的被引用记录发生删除(ON DELETE)或更新(ON UPDATE)操作时,子表中关联记录的处理规则

6.分组和聚合函数的组合使用

6.1 数据准备

-- 创建 "京东" 数据库
create database jing_dong charset=utf8;

-- 使用 "京东" 数据库
use jing_dong;

-- 创建一个商品 goods 数据表
create table goods (
id int unsigned primary key auto_increment not null,
name varchar (150) not null,
cate_name varchar (40) not null,
brand_name varchar (40) not null,
price decimal (10,3) not null default 0,
is_show bit not null default 1,
is_saleoff bit not null default 0
);

-- 向goods表中插入数据
Insert into goods values (0,'r510vc15.6 英寸笔记本','笔记本','华硕','3399',default,default);
insert into goods values (0,'y400n14.0 英寸笔记本电脑','笔记本','联想','4999',default,default);
insert into goods values (0,'g150th15.6 英寸游戏本','游戏本','雷神','8499',default,default);
insert into goods values (0,'x550cc15.6 英寸笔记本','笔记本','华硕','2799',default,default);
insert into goods values (0,'x240 超极本','超级本','联想','4880',default,default);
insert into goods values (0,'u330p13.3 英寸超极本','超级本','联想','4299',default,default);
insert into goods values (0,'svp13226scb 触控超极本','超级本','索尼','7999',default,default);
insert into goods values (0,'ipadmini7.9 英寸平板电脑','平板电脑','苹果','1998',default,default);
insert into goods values (0,'ipadair9.7 英寸平板电脑','平板电脑','苹果','3388',default,default);
insert into goods values (0,'ipadmini 配备 retina 显示屏','平板电脑','苹果','2788',default,default);
insert into goods values (0,'ideacentrec34020 英寸一体电脑','台式机','联想','3499',default,default);
insert into goods values (0,'vostro3800-r1206 台式电脑','台式机','戴尔','2899',default,default);
insert into goods values (0,'imacme086ch/a21.5 英寸一体电脑','台式机','苹果','9188',default,default);
insert into goods values (0,'at7-7414lp 台式电脑 linux)','台式机','宏碁','3699',default,default);
insert into goods values (0,'z220sfff4f06pa 工作站','服务器 / 工作站','惠普','4288',default,default);
insert into goods values (0,'poweredgeii 服务器','服务器 / 工作站','戴尔','5388',default,default);
insert into goods values (0,'macpro 专业级台式电脑','服务器 / 工作站','苹果','28888',default,default);
insert into goods values (0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',default,default);
insert into goods values (0,'商务双肩背包','笔记本配件','索尼','99',default,default);
insert into goods values (0,'x3250m4 机架式服务器','服务器 / 工作站','ibm','6888',default,default);
insert into goods values (0,'商务双肩背包','笔记本配件','索尼','99',default,default);
  • 表结构说明:
    • id 表示主键,自增
    • name 表示商品名称
    • cate_name 表示分类名称
    • brand_name 表示品牌名称
    • price 表示价格
    • is_show 表示是否显示
    • is_saleoff 表示是否售完

6.2 练习

Example1:

-- 查询类型 cate_name 为 '超级本' 的商品名称、价格
mysql> select name,price from goods where cate_name = '超级本';

Example2:

-- 显示商品的分类
mysql> select distinct(cate_name) from goods;
-- 解法2:
mysql> select cate_name from goods group by cate_name;

Example3:

-- 求所有电脑产品的平均价格,并且保留两位小数
mysql> select round(avg(price),2) from goods;

Example4:

-- 显示每种商品的平均价格
mysql> select cate_name,round(avg(price),2) from goods group by cate_name;

Example5:

-- 查询每种类型的商品中 最贵、最便宜、平均价、数量
mysql> select cate_name,max(price) as 最贵价格,min(price) as 最便宜价格, avg(price) as 平均价格, count(*) as 商品数量  from goods group by cate_name;

Exmaple6:

-- 查询所有价格大于平均价格的商品,并且按价格降序排序
-- WHERE:用于筛选原始数据行,不能使用聚合函数。
mysql> select id,name,price from goods where price > (select avg(price) from goods) order by price desc;