实际很多时候写代码写的都是业务代码,业务代码又以SQL最为常见。根据业务我们会设置很多关于连接的地方,左连接,右连接,内连接的使用不当很可能导致SQL达不到预期,可能给人感觉“SQL执行只走了一半”或者“中间有的地方跳过去,条件没有匹配返回的结果集是错误的”
一 、问题
首先要知道左连接 右连接 内连接区别
我们以左连接作为例子,
A left join B ———-》A B 左连接,也就是左边的变为主表 也就是A的数据全数取出,能跟B对应得上,B表的扩展数据也跟着展示出来,A有B没有的,B表的扩展字段也展示出来,只不过展示的是null而已。
这时候我们有的时候会在ON的后面加条件,不管你是在AND A.XXX = xxx 还是 WHERE B.XXX = xxx,你会发现有的时候这个条件加了也白加。
为什么?拿左连接为例子,你在LEFT JOIN ON A.id = B.id 后面添加关于A或者B的条件,比如说A.name=“ZP真帅”,你会发现这个筛选条件没有作用 name=”李四真帅”也出来了。因为在ON后面的条件不管是A的还是B的,返回的结果是什么,都会把主表数据先列出来。
解决方式把条件不要放在有关联的ON后面,当然是放在where里面最好,也可以放在别的不相关的关联后面。
二 、实际例子以及解决方式
这个例子就是把两个条件放后面筛选,条件并不会生效,因为是先把第一个关联的数据先列出来,这个时候就要进行筛选,不然等第二个关联的时候再筛选就会不生效。如果把 AND 改成 WHERE 则左关联会失效?
所以要注意先后顺序。。。
SELECT
jg1.id,
jg1.jgmc,
jg1.jglx,
zd.mc,
jg1.jgbm,
jg1.pid,
IFNULL(jg2.jgmc,"-") as pmc
FROM
`t_basic_zd` AS zd
INNER JOIN `t_basic_jg` AS jg1 ON zd.zdz = jg1.jglx
LEFT JOIN `t_basic_jg` AS jg2 ON jg1.pid = jg2.id
AND zd.STATUS = 'P'
AND jg1.STATUS = 'P'
解决后的代码:
SELECT
jg1.id,
jg1.jgmc,
jg1.jglx,
zd.mc,
jg1.jgbm,
jg1.pid,
IFNULL(jg2.jgmc,"-") as pmc
FROM
`t_basic_zd` AS zd
INNER JOIN `t_basic_jg` AS jg1 ON zd.zdz = jg1.jgl
AND zd.STATUS = 'P'
AND jg1.STATUS = 'P'
LEFT JOIN `t_basic_jg` AS jg2 ON jg1.pid = jg2.i
顺带提一嘴MYSQL中关于IFNULL函数:
https://blog.csdn.net/qq_41844424/article/details/103071951