sql中子查询的基本语法结构_mysql嵌套查询入门

8次阅读

子查询是mysql中解决多表逻辑依赖的刚需手段,必须用括号包裹且WHERE中的标量子查询须返回单值;IN适用于小结果集,EXISTS支持外层关联、适合大结果集;相关子查询有N×M性能风险。

sql中子查询的基本语法结构_mysql嵌套查询入门

子查询在 MySQL 中不是“可选技巧”,而是解决多表逻辑依赖的刚需手段。只要需要基于某次查询结果再做筛选、计算或关联,就绕不开它。

子查询必须用括号包裹,且不能加 LIMIT

MySQL 要求所有子查询必须用 () 明确包裹,否则直接报错 Error 1064。另外,子查询内部不能直接使用 LIMIT(除非配合 ORDER BY 且位于派生表位置)。

  • ✅ 正确:SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 100)
  • ❌ 错误:select * FROM users WHERE id IN SELECT user_id FROM orders LIMIT 10(缺括号 + 多余 LIMIT)
  • ⚠️ 特殊可用:SELECT * FROM (SELECT * FROM logs ORDER BY ts DESC LIMIT 5) AS recent(仅限 FROM 子句中的派生表)

WHERE 中的标量子查询必须返回单值

当子查询出现在 WHERE 条件右侧(如 =>BETWEEN 等)时,它必须只返回一行一列,即“标量”。否则会触发 ERROR 1242: Subquery returns more than 1 row

  • MAX() / MIN() / AVG() 聚合确保单值:WHERE salary > (SELECT AVG(salary) FROM employees)
  • LIMIT 1 强制截断(慎用,语义可能不严谨):WHERE dept_id = (SELECT id FROM departments WHERE name = 'HR' LIMIT 1)
  • 避免写成:WHERE status = (SELECT status FROM audits WHERE ref_id = 123)(若有多条 audit 记录就崩)

IN 和 EXISTS 的语义与性能差异很实际

IN 检查值是否在结果集中,适合子查询结果集小、主表大;EXISTS 是半连接语义,只关心是否存在匹配行,适合子查询结果集大、或需关联外层字段时。

SELECT name FROM customers c WHERE EXISTS (   SELECT 1 FROM orders o WHERE o.customer_id = c.id AND o.status = 'shipped' );
  • IN 子查询无法引用外部表字段:... WHERE id IN (SELECT customer_id FROM orders WHERE status = 'shipped')(只能查全部)
  • EXISTS 子查询可关联外部字段(如上例中的 c.id),这是它不可替代的关键点
  • 若子查询结果为空,IN 返回空集,EXISTS 返回 FALSE —— NULL 处理逻辑不同,会影响 NOT IN 的行为(NOT IN 遇到 NULL 直接整个条件为 UNKNOWN)

子查询最易被忽略的其实是执行顺序:MySQL 通常先执行外层查询的驱动表,再对每一行执行子查询(相关子查询),这意味着 N×M 次扫描风险真实存在。别只盯着语法对不对,先看执行计划里的 DEPENDENT SUBQUERY 出现了几次。

text=ZqhQzanResources