MySQL连接的计算顺序是什么?

MySQL连接的计算顺序是什么?,mysql,sql,join,Mysql,Sql,Join,我有以下疑问: SELECT c.* FROM companies AS c JOIN users AS u USING(companyid) JOIN jobs AS j USING(userid) JOIN useraccounts AS us USING(userid) WHERE j.jobid = 123; 我有以下问题: 使用语法与ON语法同义吗 这些连接是从左到右计算的吗?换句话说,这个查询是否表示:x=公司加入用户;y=x加入工作;z=y加入用户帐户 如果问题2的答案是肯定的,

我有以下疑问:

SELECT c.*
FROM companies AS c
JOIN users AS u USING(companyid)
JOIN jobs AS j USING(userid)
JOIN useraccounts AS us USING(userid)
WHERE j.jobid = 123;
我有以下问题:

  • 使用语法与ON语法同义吗
  • 这些连接是从左到右计算的吗?换句话说,这个查询是否表示:x=公司加入用户;y=x加入工作;z=y加入用户帐户
  • 如果问题2的答案是肯定的,那么假设companys表有companyid、userid和jobid列是否安全
  • 我不明白当WHERE子句引用别名“j”时,如何使用WHERE子句来拾取COMPANYS表上的行
  • 任何帮助都将不胜感激

    从这里开始阅读:


    加入MySQL 5.0.12中的处理更改

    从MySQL 5.0.12开始,根据SQL:2003标准处理自然连接和使用连接,包括外部连接变体。我们的目标是使MySQL的语法和语义与自然连接和连接保持一致。。。根据SQL:2003使用。但是,联接处理中的这些更改可能会导致某些联接的不同输出列。此外,一些在旧版本中似乎正常工作的查询必须重写以符合该标准

    这些变化主要有五个方面:

    • MySQL确定自然或使用join操作的结果列(以及整个FROM子句的结果)的方式

    • 展开SELECT*并选择tbl_name.*进入所选列的列表

    • 在自然联接或使用联接中解析列名

    • 将自然连接或使用连接转换为连接。。。开

    • 在联接条件下解析列名称。。。开


      • 我无法回答有关使用语法的问题。真奇怪。我以前从未见过它,总是用ON子句来代替

        但我可以告诉您的是,连接操作的顺序是由查询优化器在构建其查询计划时根据优化启发式系统动态确定的,其中一些是:

      • 是否对主键字段执行联接?如果是这样,则在查询计划中获得高优先级

      • 是否在外键字段上执行联接?这也得到了高度重视

      • 联接字段上是否存在索引?如果是这样的话,就降低优先级

      • 是否对WHERE子句中的字段执行联接操作?WHERE子句表达式是否可以通过检查索引(而不是执行表扫描)进行计算?这是一个重要的优化机会,因此它获得了一个重要的优先级提升

      • 连接列的基数是多少?具有高基数的列为优化器提供了更多机会来区分错误匹配(那些不满足WHERE子句或ON子句的匹配),因此高基数连接通常在低基数连接之前处理

      • 联接表中实际有多少行?与具有一千万行的表相比,针对只有100个值的表进行连接所产生的数据爆炸更少

      • 无论如何。。。关键是。。。查询执行计划中有很多变量。如果您想了解MySQL如何优化其查询,请使用EXPLAIN语法

        下面是一篇好文章:


        编辑时:

        回答第四个问题:您不是在查询“companys”表。您正在查询FROM和USING子句中所有四个表的联接叉积


        “j.jobid”别名只是该联接表集合中一列的完全限定名。

        我不确定ON-vs-USING部分(尽管这表示它们是相同的)

        至于排序问题,它的实现(可能是查询)是完全特定的。MYSQL很可能在编译请求时选择一个顺序。如果要强制执行特定的顺序,则必须“嵌套”查询:

        SELECT c.*
        FROM companies AS c 
            JOIN (SELECT * FROM users AS u 
                JOIN (SELECT * FROM  jobs AS j USING(userid) 
                      JOIN useraccounts AS us USING(userid) 
                      WHERE j.jobid = 123)
            )
        
        对于第4部分:where子句,它限制了jobs表中哪些行有资格加入。因此,如果有行由于匹配的userid而要连接,但没有正确的jobid,那么它们将被忽略。

        1)使用与on不完全相同,但两个表都有一个与您要连接的名称相同的列,这是一种简写。。。见:

        在我看来,阅读起来比较困难,所以我会去拼写连接

        3) 这个问题并不清楚,但我猜不清楚

        2) 假设您是通过其他表(并非所有表都直接在公司上)连接的,则此查询中的顺序并不重要。。。见以下比较:

        原版:

        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u USING(companyid) 
            JOIN jobs AS j USING(userid) 
            JOIN useraccounts AS us USING(userid) 
        WHERE j.jobid = 123
        
        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u on u.companyid = c.companyid
            JOIN jobs AS j on j.userid = u.userid
            JOIN useraccounts AS us on us.userid = u.userid 
        WHERE j.jobid = 123
        
        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u on u.companyid = c.companyid
            JOIN jobs AS j on j.userid = c.userid
            JOIN useraccounts AS us on us.userid = c.userid
        WHERE j.jobid = 123
        
        我认为它可能暗示的是:

        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u USING(companyid) 
            JOIN jobs AS j USING(userid) 
            JOIN useraccounts AS us USING(userid) 
        WHERE j.jobid = 123
        
        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u on u.companyid = c.companyid
            JOIN jobs AS j on j.userid = u.userid
            JOIN useraccounts AS us on us.userid = u.userid 
        WHERE j.jobid = 123
        
        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u on u.companyid = c.companyid
            JOIN jobs AS j on j.userid = c.userid
            JOIN useraccounts AS us on us.userid = c.userid
        WHERE j.jobid = 123
        
        您可以在此处切换加入jobs&usersaccounts的线路

        如果公司里的所有东西都加入进来会是什么样子:

        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u USING(companyid) 
            JOIN jobs AS j USING(userid) 
            JOIN useraccounts AS us USING(userid) 
        WHERE j.jobid = 123
        
        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u on u.companyid = c.companyid
            JOIN jobs AS j on j.userid = u.userid
            JOIN useraccounts AS us on us.userid = u.userid 
        WHERE j.jobid = 123
        
        SELECT c.* 
            FROM companies AS c 
            JOIN users AS u on u.companyid = c.companyid
            JOIN jobs AS j on j.userid = c.userid
            JOIN useraccounts AS us on us.userid = c.userid
        WHERE j.jobid = 123
        
        这真的没有逻辑意义。。。除非每个用户都有自己的公司

        4.)sql的神奇之处在于,您只能显示某些列,但所有列都是用于排序和筛选的列

        如果你回来

        SELECT c.*, j.jobid....  
        
        您可以清楚地看到它在过滤什么,但是数据库服务器并不关心您是否输出一行进行过滤

      • 使用(fieldname)是在table1.fieldname=table2.fieldname上的一种简写表达方式


      • SQL没有定义连接的“顺序”,因为这不是语言的本质。显然,必须在语句中指定顺序,但是内部联接可以被认为是可交换的:您可以按任何顺序列出它们,您将得到相同的结果

        这就是说,当构建一个选择。。。JOIN,尤其是包含左联接的联接,我发现将第三个联接视为将新表联接到第一个联接的结果,将第四个联接视为将