问题:LEFT JOIN 和 INNER JOIN 的区别是什么?在什么场景下使用 LEFT JOIN 会导致性能问题?
INNER JOIN(内连接)只返回两个表中联结字段相等的行。而 LEFT JOIN(左连接)返回左表中所有的记录,以及右表中联结字段相等的记录。如果右表中没有匹配,则结果为 NULL。
性能陷阱:当 RIGHT 表(右表)数据量巨大,且 LEFT JOIN 的条件字段没有索引时,MySQL 可能会进行全表扫描。此外,如果在 WHERE 子句中直接过滤右表的字段(例如 WHERE right_table.col = 1),会将 LEFT JOIN 隐式转换为 INNER JOIN,从而失去左表全量数据的特性。
-- 错误示例:WHERE 条件过滤了右表,导致性能下降且逻辑改变
SELECT a., b.
FROM table_a a
LEFT JOIN table_b b ON a.id = b.a_id
WHERE b.status = 1; -- 这变成了 INNER JOIN
-- 正确示例:将右表过滤条件放在 ON 中
SELECT a., b.
FROM table_a a
LEFT JOIN table_b b ON a.id = b.a_id AND b.status = 1;
问题:GROUP BY 中为什么不能使用 WHERE?HAVING 的作用是什么?
WHERE 在分组(GROUP BY)之前进行过滤,它不能与聚合函数(如 COUNT, SUM)一起使用。而 HAVING 是在分组之后进行过滤,它可以配合聚合函数使用。
执行顺序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。理解这个顺序是解决复杂查询问题的关键。
-- 查询销售额超过10000元的商品类别
SELECT category_id, SUM(amount) as total_sales
FROM orders
WHERE create_time > '2023-01-01' -- 先过滤时间,减少分组数据量
GROUP BY category_id
HAVING total_sales > 10000; -- 再过滤聚合结果
问题:EXISTS 和 IN 的区别?何时使用 EXISTS 性能更优?
IN 是先执行子查询,将结果集传给外层查询。适用于子查询结果集较小的情况。EXISTS 是对外层查询逐条扫描,检查子查询是否返回结果。适用于主表数据小,子查询数据大的情况。
优化建议:如果主表(外层)数据量远小于子查询(内层)数据量,使用 EXISTS 通常更快,因为它可以利用索引提前终止扫描。反之,使用 IN。
-- 推荐:当 users 表很小,orders 表很大时
SELECT FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);