INNER JOIN只保留两表匹配的行,不匹配的整行丢弃;连接条件必须写在ON子句中,不可置于WHERE后,且需用表别名避免字段冲突、确保类型一致与NULL安全。

INNER JOIN 只保留两张表中匹配的行,不匹配的记录会被直接丢弃。
INNER JOIN 的基本语法和连接条件写在哪
连接条件必须写在 ON 子句里,不能放在 WHERE 后面(虽然某些简单场景下结果看似一样,但逻辑不同,且可能影响执行计划)。ON 是连接发生时的判断依据,WHERE 是连接完成后的过滤。
- 正确写法:
SELECT * FROM orders INNER JOIN customers ON orders.customer_id = customers.id - 错误习惯(逻辑混淆):
SELECT * FROM orders INNER JOIN customers WHERE orders.customer_id = customers.id—— 这会触发隐式 CROSS JOIN + WHERE 过滤,性能差且语义不清 - 如果需要多条件,用
AND连接:ON a.id = b.order_id AND b.status = 'active'
别名对可读性和字段歧义的关键作用
两张表有同名字段(比如都含 id 或 name)时,不加表别名会导致查询报错或结果不可控。别名不是可选项,是必须项。
- 必须为每张表指定简短别名:
FROM orders o INNER JOIN customers c ON o.customer_id = c.id - 引用字段时带上别名:
SELECT o.id, c.name, o.total—— 否则SELECT id会报错 - 别名还能简化长表名或带 schema 的表:
FROM sales.order_items oi
为什么结果行数比预期少?常见漏匹配原因
INNER JOIN 返回的是交集,以下情况都会导致行数“变少”,不是 bug,是设计行为:
-
NULL值不会被匹配:如果orders.customer_id有NULL,这些订单不会出现在结果里 - 数据类型不一致:比如一边是
VARCHAR带空格,另一边是INT,隐式转换失败导致匹配不上 - 大小写或字符集差异:MySQL 默认不区分大小写,但 PostgreSQL 和 SQL Server 可能区分;
utf8mb4_bin排序规则下'A'≠'a' - 连接字段存在重复值:一张表里
customer_id = 100有 3 条,另一张有 2 条,结果会返回 3 × 2 = 6 行 —— 容易误以为“多连了”
真正容易被忽略的,是把 INNER JOIN 当成“安全默认”——它天然丢数据。要查全量订单及对应客户信息(包括无客户记录的订单),就得换 LEFT JOIN,而不是硬调 INNER JOIN 加 OR ... IS NULL 补救。

















