MySQL杂ces
学习过程中,遇到的问题,值得注意的点
JOIN VS LEFT JOIN
在数据库中,LEFT JOIN
和普通的 JOIN
(默认是 INNER JOIN
)是两种不同的连接方式,用来组合两个或多个表的数据。它们的区别主要在于是否保留左表中的所有记录。
🔹 JOIN
或 INNER JOIN
(内连接)
只返回两个表中“匹配”的记录。
如果某一行在其中一个表中没有匹配项,该行就不会出现在结果中。
示例:
1 | SELECT * |
结果:只包含 A 和 B 表中 id 匹配的行。
🔸 LEFT JOIN
(左连接)
返回左表中的所有记录,即使在右表中没有匹配项。
如果右表没有匹配的记录,则右表的字段为
NULL
。
示例:
1 | SELECT * |
结果:包含 A 表的所有记录,若 B 中有匹配则带上 B 表的数据;若没有匹配,则 B 表的字段为 NULL
。
表 A(学生):
id | name |
---|---|
1 | 小明 |
2 | 小红 |
3 | 小刚 |
表 B(成绩):
a_id | score |
---|---|
1 | 90 |
2 | 85 |
INNER JOIN 查询结果:
1 | SELECT * FROM A JOIN B ON A.id = B.a_id; |
id | name | a_id | score |
---|---|---|---|
1 | 小明 | 1 | 90 |
2 | 小红 | 2 | 85 |
LEFT JOIN 查询结果:
1 | SELECT * FROM A LEFT JOIN B ON A.id = B.a_id; |
id | name | a_id | score |
---|---|---|---|
1 | 小明 | 1 | 90 |
2 | 小红 | 2 | 85 |
3 | 小刚 | NULL | NULL |
✅ 总结一句话:
JOIN
(默认是INNER JOIN
):只取匹配的记录。LEFT JOIN
:保留左表所有记录,右表无匹配时补NULL
。
GROUP BY AND HAVING
GROUP BY
是 SQL 中用来对查询结果进行分组的关键字,通常会和聚合函数(如 COUNT()
、SUM()
、AVG()
、MAX()
、MIN()
等)一起使用,用来对每个组进行统计或运算。
WHERE
是在分组前过滤数据,而HAVING
是在分组后过滤数据。
🔹 基本语法
1 | SELECT 列名, 聚合函数(...) |
销售表 sales
:
id | seller | amount |
---|---|---|
1 | 张三 | 100 |
2 | 李四 | 200 |
3 | 张三 | 150 |
4 | 王五 | 300 |
❓ 统计每个人的销售总额:
1 | SELECT seller, SUM(amount) AS total_sales |
查询结果:
seller | total_sales |
---|---|
张三 | 250 |
李四 | 200 |
王五 | 300 |
🧠 注意事项
GROUP BY
后面的字段,必须是你在SELECT
中使用的非聚合字段。如果你在
SELECT
中用了非聚合字段,它必须出现在GROUP BY
中(除非你使用了某些数据库的特殊语法,比如 MySQL 的ONLY_FULL_GROUP_BY
没开启时可以例外)。
🔍 常见聚合函数搭配用法
常用聚合函数表
函数名 | 作用 |
---|---|
COUNT(*) |
统计每组的记录数 |
SUM() |
求和 |
AVG() |
计算平均值 |
MAX() |
获取最大值 |
MIN() |
获取最小值 |
每个函数都用于对一组值执行计算,并返回单个值,通常与GROUP BY
子句一起使用。
✨ 进阶用法:配合 HAVING
使用
WHERE
是在分组前过滤数据,而 HAVING
是在分组后过滤数据。
举例:只查出销售额超过 200 的销售员
1 | SELECT seller, SUM(amount) AS total_sales |
✅ 总结一句话:
GROUP BY
是用来把结果按某一列分组的;通常结合聚合函数使用;
如果你想对分组后的结果再筛选,记得用
HAVING
而不是WHERE
。
EXISTS AND NOT EXISTS
EXISTS
和 NOT EXISTS
是 SQL 中非常有用的子查询语法,用于判断某个子查询是否返回结果,结果为布尔值:存在则为 TRUE
,否则为 FALSE
。
🔹 EXISTS 的作用
EXISTS 判断子查询是否返回至少一行记录。
1 | SELECT * |
📌 只要子查询结果存在任何一行,EXISTS
就返回 TRUE
,当前行就会被选中。
示例
表:students
id | name |
---|---|
1 | 小明 |
2 | 小红 |
3 | 小刚 |
表:scores
student_id | score |
---|---|
1 | 90 |
1 | 85 |
2 | 78 |
❓ 找出有成绩记录的学生:
1 | SELECT * |
查询结果:
id | name |
---|---|
1 | 小明 |
2 | 小红 |
✅ 小刚没有成绩记录,所以被排除了。
这个查询使用了 EXISTS
子查询,它会检查对于 students
表中的每个学生,scores
表中是否存在对应的记录。只有当存在匹配的记录时,该学生才会被包含在结果中。
🔸 NOT EXISTS 的作用
NOT EXISTS 判断子查询是否不返回任何结果
,即判断“不存在”
1 | SELECT * |
🌰 示例
继续用上面的表:
❓ 想找出没有成绩记录的学生:
1 | SELECT * |
查询结果:
id | name |
---|---|
3 | 小刚 |
✅ 因为小刚在 scores
表中找不到成绩记录。
💡 EXISTS vs IN vs JOIN 简要比较
用法 | 推荐场景 |
---|---|
EXISTS |
子查询结果比较复杂、带多个字段时 |
IN |
子查询只返回单列,且数据量不大时 |
JOIN |
需要获取两个表的具体字段值时 |
这个查询使用了 NOT EXISTS
子查询,它会检查对于 students
表中的每个学生,在 scores
表中是否不存在对应的记录。只有当没有匹配的记录时,该学生才会被包含在结果中
三种查询方式的比较:
EXISTS
:适合条件复杂的子查询,效率较高IN
:适合简单的单列值匹配,数据量小时使用JOIN
:需要同时获取两个表的字段时最合适
🔧 一般来说,EXISTS
在处理是否存在逻辑时更高效,尤其是在子查询中带有复杂条件或多个表联结的时候。