我可以指定连接的顺序吗?

时间:2011-10-04 17:12:21

标签: mysql join left-join inner-join

假设我有三个表,A,B和C.概念上A(可选)有一个B,B(总是)有一个C.

Table A:
a_id
... other stuff

Table B:
a_fk_id (foreign key to A.a_id, unique, primary, not null)
c_fk_id (foreign key to C.c_id, not null)
... other stuff

Table C:
c_id
... other stuff

我想选择A中的所有记录以及B和C中的相关记录(如果存在)。但是,如果B和C都存在,则B和C数据必须仅出现在结果中。

我觉得我想做:

SELECT *
FROM
    A
    LEFT JOIN B on A.a_id=B.a_fk_id
    INNER JOIN C on B.c_fk_id=C.c_id

但是Joins似乎是左关联的(第一次连接发生在第二次连接之前),所以这不会给A中没有C条目的记录。

AFAICT我必须使用子查询,类似于:

SELECT *
FROM
    A
    LEFT JOIN (
        SELECT * FROM B INNER JOIN C ON B.c_fk_id=C.c_id
    ) as tmp ON A.id = tmp.a_fk_id

但是一旦我在查询中有几个这样的关系(实际上我可能有两个或三个嵌套),我担心代码复杂性和查询优化器。

除了这个子查询方法之外,我有没有办法指定连接顺序?

感谢。

4 个答案:

答案 0 :(得分:4)

在SQL Server中,您可以执行

SELECT *
FROM   a
       LEFT JOIN b
                 INNER JOIN c
                   ON b.c_fk_id = c.c_id
         ON a.id = b.a_fk_id  

ON子句的位置意味着LEFT JOIN上的b在逻辑上最后发生。据我所知这是标准的(claimed to be ANSI prescribed here),但我确信如果在MySQL中不起作用,downvotes会通知我!

答案 1 :(得分:2)

编辑:这就是我说话的速度比我想象的要快。我之前的解决方案不起作用,因为'c'尚未加入。让我们再试一次。

我们可以使用WHERE子句将结果限制为仅匹配您正在查找的条件,其中C具有有效(IS NOT NULL)或B没有值(IS NULL)。像这样:

SELECT *
FROM a
    LEFT JOIN b ON (b.a = a.a)
    LEFT JOIN c ON (c.b = b.b)
WHERE (c.c IS NOT NULL OR b.b IS NULL);

没有WHERE结果:

mysql> SELECT * FROM a LEFT JOIN b ON (b.a = a.a) LEFT JOIN c ON (c.b = b.b);
+------+------+------+------+------+
| a    | a    | b    | c    | b    |
+------+------+------+------+------+
|    1 |    1 |    1 |    1 |    1 |
|    1 |    1 |    2 | NULL | NULL |
|    2 |    2 |    3 |    2 |    3 |
|    3 | NULL | NULL | NULL | NULL |
|    4 | NULL | NULL | NULL | NULL |
+------+------+------+------+------+

使用WHERE结果:

mysql> SELECT * FROM a LEFT JOIN b ON (b.a = a.a) LEFT JOIN c ON (c.b = b.b) WHERE (c.c IS NOT NULL OR b.b IS NULL);
+------+------+------+------+------+
| a    | a    | b    | c    | b    |
+------+------+------+------+------+
|    1 |    1 |    1 |    1 |    1 |
|    2 |    2 |    3 |    2 |    3 |
|    3 | NULL | NULL | NULL | NULL |
|    4 | NULL | NULL | NULL | NULL |
+------+------+------+------+------+

答案 2 :(得分:0)

是的,您使用STRAIGHT_JOIN进行此操作 使用此关键字时,将按照您指定的确切顺序进行连接。

请参阅:http://dev.mysql.com/doc/refman/5.5/en/join.html

答案 3 :(得分:0)

好吧,我也想到了另一个解决方案,我发布它是为了完整性(虽然我实际上是在使用Martin的答案)。

使用RIGHT JOIN:

SELECT 
    *
FROM
    b
    INNER JOIN c ON b.c_fk_id = c.c_id
    RIGHT JOIN a ON a.id = b.a_fk_id

我很确定我读到的关于JOINS的每一篇文章都说RIGHT JOIN是毫无意义的,但你就是。