实际很多时候写代码写的都是业务代码,业务代码又以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里面最好,也可以放在别的不相关的关联后面。
二 实际例子以及解决方式
这个例子就是把两个条件(uvr.user_id = 10023 ,uvr.target_type = 2)放在第一个左连接后面还是放在where后面都不生效,其中一个问题是左连接ON后面条件失效的问题还有一个关于是OR的问题
SELECT
uvr.id,
uvr.user_id,
uvr.target_type,
uvr.target_id,
uvr.create_time,
ui.head_img_url AS avatar,
temp.`goods_name`,
temp.head_img_url,
temp.second_hand_price,
ud.type
FROM
user_view_record uvr
LEFT JOIN user_info ui ON uvr.user_id = ui.id
AND uvr.user_id = 10023
AND uvr.target_type = 2
INNER JOIN goods temp ON uvr.target_id = temp.id
LEFT JOIN user_detail ud ON uvr.user_id = ud.user_id
WHERE
uvr.user_id < 100000 OR uvr.user_id > 200000
ORDER BY
create_time DESC
解决后的代码
其实不是很建议我下面的方法,还是最好把条件放在where里面,出现where后面的条件不生效是因为 OR的问题,你把它当成正常的代码分析一下逻辑就知道,解决也很好解决,加个括号什么的就好了。
SELECT
uvr.id,
uvr.user_id,
uvr.target_type,
uvr.target_id,
uvr.create_time,
ui.head_img_url AS avatar,
temp.`goods_name`,
temp.head_img_url,
temp.second_hand_price,
ud.type
FROM
user_view_record uvr
LEFT JOIN user_info ui ON uvr.user_id = ui.id
INNER JOIN goods temp ON uvr.target_id = temp.id
AND uvr.user_id = 10023
AND uvr.target_type = 2
LEFT JOIN user_detail ud ON uvr.user_id = ud.user_id
WHERE
uvr.user_id < 100000 OR uvr.user_id > 200000
ORDER BY
create_time DESC