V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
liunaijie
V2EX  ›  MySQL

这两种查询的实现,有什么区别?什么场景下使用 join?

  •  
  •   liunaijie · 2019-10-14 11:23:51 +08:00 · 6519 次点击
    这是一个创建于 1628 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有这么两张表
    学生表 a
    (id,name)
    成绩表 b
    (id,a_id,score)
    然后查询张三的成绩。
    我之前都是用:

    select b.score from a,b where a.name = '张三' and a.id = b.a_id
    

    这两天面试的时候一个面试官问我,这个用 join 怎么写。

    select b.score from b left join a on a.id = b.a_id where a.name = '张三'
    

    请问一下,这两种实现在性能上有什么区别吗?我一般不会去用 join 写,什么场景下要用 join 这么写?

    17 条回复    2019-10-15 09:06:13 +08:00
    clarkyi
        1
    clarkyi  
       2019-10-14 11:25:38 +08:00
    explain 一下你就知道了
    lihongjie0209
        2
    lihongjie0209  
       2019-10-14 11:26:04 +08:00
    select b.score from a,b 这是笛卡尔积, 要爆炸的。
    liprais
        3
    liprais  
       2019-10-14 11:41:20 +08:00   ❤️ 1
    select b.score from a,b where a.name = '张三' and a.id = b.a_id
    等价于
    select b.score from b inner join a on a.id = b.a_id where a.name = '张三'
    reus
        4
    reus  
       2019-10-14 11:46:20 +08:00
    首先学会用 explain,然后你就能自己分析,不需要问人了。
    qwerthhusn
        5
    qwerthhusn  
       2019-10-14 11:47:36 +08:00
    from a join b on a.c = b.d 这个是内连接和 inner join 是一样的效果
    from a join b on a.c = b.d(+) 这个是左连接还是右连接忘记了,MySQL 不支持(+)连接符,Oracle 是支持的,但是一般都是推荐用 left|right join...on...这种,因为(+)有点不好理解


    @lihongjie0209 where 条件会限制不是笛卡尔集的
    newtype0092
        6
    newtype0092  
       2019-10-14 11:59:59 +08:00
    什么情况下都应该使用 join,from a,b 这种是满足特定条件的简便写法,你不知道原本含义的话就不要使用简便写法防止踩坑。
    inner join 的问题在于如果学生没有成绩结果里是没有这行的,如果有 3 个张三,某个没有成绩,你这个结果只会返回 2 行(假设 1 个学生最多只有 1 个成绩的情况下)
    left join 能保证左表数据是完整的
    wangyzj
        7
    wangyzj  
       2019-10-14 12:04:11 +08:00
    永远用 join
    用笛卡尔积会炸
    zsy979
        8
    zsy979  
       2019-10-14 13:34:33 +08:00
    第一个 sql 是 a*b 行数的临时表再 where
    第二个 sql 是 on 后的临时表再 where
    zhuyichen1017
        9
    zhuyichen1017  
       2019-10-14 14:01:51 +08:00
    我觉得 Mysql 的优化器应该不会去做笛卡尔积吧
    Aresxue
        10
    Aresxue  
       2019-10-14 15:26:51 +08:00
    扫描行数的区别,看下执行计划
    x66
        11
    x66  
       2019-10-14 15:51:18 +08:00
    MySQL 8.0 实测并不会生成笛卡尔积。。
    从 explain 上来看也并没有什么区别。。
    huijiewei
        12
    huijiewei  
       2019-10-14 15:54:15 +08:00
    这两种实现的数据结果完全是不一样的。所以没有性能区别
    huijiewei
        13
    huijiewei  
       2019-10-14 15:55:37 +08:00
    up 我看到了 a 表的限定,所以没有区别,没有 A 表限定的话就有区别了
    sadfQED2
        14
    sadfQED2  
       2019-10-14 16:16:44 +08:00 via Android
    @x66 MySql5.7 实测也没生成笛卡尔积,而且 explain 也没有什么区别
    Shaw314
        15
    Shaw314  
       2019-10-14 16:28:34 +08:00
    如果第一句写成 inner join on 的话,可能性能会好一点,查询优化器可以选择查询成本较小的连接循序🙄
    NotFoundEgg
        16
    NotFoundEgg  
       2019-10-14 16:59:31 +08:00
    个人认为在像你例子中这种简单的 sql 两者是等价的,但是在以后的实际工作中多表联查使用你第一种写法会爆炸的,所以养成好习惯,能 left join 的请一律 left join
    liouop
        17
    liouop  
       2019-10-15 09:06:13 +08:00 via Android
    select from 两张表 是隐式调用 inner join,直接产生笛卡尔积。具体可以看一下 mysql 必知必会,查一下隐式与显式的区别。主要区别在于前面有人讲到的,on 与 where,on 会先筛选再连接,where 也是连接再条件判断
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5364 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 08:03 · PVG 16:03 · LAX 01:03 · JFK 04:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.