携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
1 前言
也算是我孤陋寡闻了,也是没好好研究sql。今天写了一个奇慢的sql,还找不出来原因。最后发现竟然没有where,加了条件判断,没有where也可以吗???吓得我赶紧写了个sql测了一下。
SELECT * FROM `user` id = 1;
> 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '= 1' at line 1
> 时间: 0.02s
是的,我没加where,幸亏报错了,不然我这么多年的sql岂不是白写了。。。。
2 问题
是这样的,假如我们有两张表。俺瞎编的表,总不能拿俺们真实的数据来霍霍。
userinfo表,user信息,为了演示id和age有索引,下边好几百个多多不用管,那是为了演示添加的数据。
wife表,user的配偶信息,为了演示,id和age有索引,下边的多多媳妇也不用管。
然后嘞,那个奇慢的sql长这样
SELECT
userinfo.name,
userinfo.age,
wife.wife_name,
wife.wife_age
FROM
userinfo LEFT JOIN wife ON userinfo.id = wife.user_id
AND userinfo.age = 24
AND wife.wife_age = 25;
注意,这里没加where。好吧,其实我是删了一个条件,带着where一起删了,忘给人加回去了。
但是它竟然还能跑,还能跑。。。但是按照逻辑来说,这里限制了user的age是24,wife的age是25.那其实就应该只有小明符合条件。返回数据应该就只有一条。
但是,重点来了,它的返回竟然是这样的。
这啥玩意。。。别急,还有性能问题
跑的贼慢贼慢。一个查询页面打开,用了6秒。差点被老大揍一顿。。。。
就解释了一下:
EXPLAIN
SELECT
userinfo.name,
userinfo.age,
wife.wife_name,
wife.wife_age
FROM
userinfo LEFT JOIN wife ON userinfo.id = wife.user_id
AND userinfo.age = 24
AND wife.wife_age = 25;
啥,userinfo竟然全表扫了。为啥,为啥又多了数据,userinfo.age = 24 是买的看票吗?啥作用没有?
但是改成WHERE
结果:
还走了索引,快滴多。。。
3 探索
好了,想想也是这个AND出了问题。
就查询了一下,其实是left join on and的问题
left join on 后边的on条件是生成临时表的条件,不管on后边的条件是否成立,都会返回左表的所有数据。 我这里的AND userinfo.age = 24 AND wife.wife_age = 25;都变成了ON后边的条件,那么userinfo的数据就将全部返回。这都全部返回了,我用个鸡儿的索引啊。然后嘞,这里对左表的筛选条件不起任何作用,也不会对结果产生影响。对右表的过滤条件则会进行过滤,将符合条件的数据与左表进行关联返回。 怪不得,怪不得,user全出来了,老婆就小明有。
然而当使用where的时候:
where其作用是当左右表关联成功之后,对结果产生作用。这时左右表都会根据筛选条件进行返回。 也就是使用where的时候,条件才起作用。
还有还有,那join呢?
直接上结果
不加where的
SELECT
userinfo.name,
userinfo.age,
wife.wife_name,
wife.wife_age
FROM
userinfo JOIN wife ON userinfo.id = wife.user_id
AND userinfo.age = 24
AND wife.wife_age = 25;
使用where的
SELECT
userinfo.name,
userinfo.age,
wife.wife_name,
wife.wife_age
FROM
userinfo JOIN wife ON userinfo.id = wife.user_id
WHERE userinfo.age = 24
AND wife.wife_age = 25;
再来解释一下:
哇哇哇,一毛一样。
所以:
这里若是使用 inner join on后边接AND或者是WHERE就没有区别了,不管条件是针对左表的还是右表的,都会对生成的临时表进行过滤。
所以,刺激吧,写个bug还能学个点。想想就刺激。
最后,祝各位大佬们,bug多多,天天改,天天学。