我可以指定连接发生的顺序吗?
假设我有三个表,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
但是连接似乎是左关联的(第一个连接发生在第二个连接之前),所以这不会给出来自 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
但是一旦我在查询中有几个这样的关系(实际上我可能有两个或三个嵌套的),我就担心代码复杂性和查询优化器。
除了这个子查询方法之外,还有其他方法可以指定连接顺序吗?
谢谢。
Say I have three tables, A, B and C. Conceptually A (optionally) has one B, and B (always) has one 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
I want to select All records from A as well as their associated records from B and C if present. However, the B and C data must only occur in the result if both B and C are present.
I feel like I want to do:
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
But Joins seem to be left associative (the first join happens before the second join), so this will not give records from A that don't have an entry in C.
AFAICT I must use sub queries, something along the lines of:
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
but once I have a couple of such relationships in a query (in reality I may have two or three nested), I'm worried both about code complexity and about the query optimizer.
Is there a way for me to specify the join order, other than this subquery method?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 SQL Server 中,您可以执行
ON
子句的位置意味着b
上的LEFT JOIN
逻辑上最后发生。据我所知,这是标准的(声称这里是 ANSI 规定的 )但我确信如果它在 MySQL 中不起作用,反对票会通知我!In SQL Server you can do
The position of the
ON
clause means that theLEFT JOIN
onb
logically happens last. As far as I know this is standard (claimed to be ANSI prescribed here) but I'm sure the downvotes will notify me if it doesn't work in MySQL!编辑:这就是我说话速度比我想象的要快的结果。我之前的解决方案不起作用,因为“c”尚未加入。让我们再试一次。
我们可以使用 WHERE 子句将结果限制为仅匹配您要查找的条件的结果,其中 C 具有有效值 (IS NOT NULL) 或 B 没有值 (IS NULL)。像这样:
没有 WHERE 结果:
有 WHERE 结果:
Edit: And that's what I get for talking faster than I think. My previous solution doesn't work because 'c' hasn't been joined yet. Let's try this again.
We can use a WHERE clause to limit the results to only those that match the criteria you're looking for, where C has a valid (IS NOT NULL) or B does not have a value (IS NULL). Like this:
Without WHERE Results:
With WHERE Results:
是的,您可以使用
STRAIGHT_JOIN
来实现此目的。使用此关键字时,连接将按照您指定的确切顺序发生。
请参阅: http://dev.mysql.com/doc/refman/5.5 /en/join.html
Yes, you use the
STRAIGHT_JOIN
for this.When using this keyword the join will occur in the exact order that you specify.
See: http://dev.mysql.com/doc/refman/5.5/en/join.html
好吧,我还想出了另一个解决方案,为了完整性我将其发布(尽管我实际上使用了马丁的答案)。
使用 RIGHT JOIN:
我很确定我读过的关于 JOINS 的每一篇文章都说 RIGHT JOIN 毫无意义,但事实就是如此。
Well, I thought up another solution as well, and I'm posting it for completeness (Though I'm actually using Martin's answer).
Use a RIGHT JOIN:
I'm pretty sure every piece I've read about JOINS said that RIGHT JOINs were pointless, but there you are.