为什么该RIGHT JOIN查询返回了state非pending的发票记录?
RIGHT JOIN执行逻辑与结果原因说明
核心规则前置
- JOIN的ON条件仅控制两张表的关联匹配规则,不会过滤**RIGHT JOIN的保留表(即右表)**的任何行,仅会决定左表能否匹配到对应值。
- RIGHT JOIN的核心特性:完整保留右表的所有行,左表行满足ON条件时返回匹配值,不满足的位置补NULL。
你的SQL分步执行过程
你执行的SQL如下:
SELECT _user.id AS userId, _user.name AS userName, _user.state AS userState, _invoice.id AS invoiceId, _invoice.userId AS invoiceUserId, _invoice.`state` AS invoiceState FROM _user RIGHT JOIN _invoice on _invoice.state = 'pending'
执行分为三步:
- 确定保留表:RIGHT JOIN右侧的
_invoice是保留表,最终结果一定会包含该表的全部行,不受ON条件影响。 - 执行ON关联匹配:遍历
_invoice的每一行,判断是否满足_invoice.state = 'pending'的条件:- 若满足条件:由于你的ON条件没有写两表的关联键(比如
_user.id = _invoice.userId),所以该行会和_user表的所有行做笛卡尔积匹配,生成N行结果(N为_user表的行数)。 - 若不满足条件:
_user表对应的所有字段直接补NULL,保留_invoice当前行的全部原值。
- 若满足条件:由于你的ON条件没有写两表的关联键(比如
- 输出SELECT指定字段:得到你看到的最终查询结果。
结果验证示例
结合常规的表数据场景,假设:
_user表有2条有效用户数据_invoice表有3条数据,仅1条state为pending
执行后得到的结果会是:2行匹配到用户的pending发票数据 + 2行补NULL的非pending发票数据,和你拿到的返回结果完全一致。
常见误区说明
你之前在LEFT JOIN中用ON做筛选生效,是因为LEFT JOIN的保留表是左表,给右表加ON筛选条件时,不满足条件的右表字段补NULL,看起来像是筛选了右表行。但RIGHT JOIN的保留表是右表,你给右表加ON筛选条件,只会影响左表的匹配结果,不会过滤右表的任何行,所以才会出现state为非pending的行也被返回的情况。
如果要过滤_invoice表仅保留state为pending的行,需要将条件放在WHERE子句中,或者提前在右表的子查询中完成筛选。
内容的提问来源于stack exchange,提问作者Lukas Liesis
相关产品推荐
相关产品推荐

