我有一堆表,比方说 A、B1、B2、C1、C2。
我从 A 中选择,在 B1 上加入,它本身在 B2 上加入。我也在 C1 上选择 A,它本身加入 C2,我的意思是:
SELECT *
FROM A
JOIN B1 ON A.b1 = B1.id
JOIN B2 ON B1.b2 = B2.id
LEFT JOIN C1 ON A.c1 = C1.id
LEFT JOIN C2 ON C1.c2 = C2.id
如果 B 分支失败,我希望整个查询失败,这是通过那些 JOIN 干净地完成的。
但我也希望“C”的分支在 LEFT JOIN C2
失败时失败(在这种情况下我不想要来自 C1 的信息,我想要 NULLS),但我仍然如果 C 分支失败,则希望整个查询成功。
所以我需要一种:
SELECT *
FROM A
JOIN B1 ON A.b1 = B1.id
JOIN B2 ON B1.b2 = B2.id
LEFT JOIN (C1 ON A.c1 = C1.id
JOIN C2 ON C1.c2 = C2.id)
但据我所知,这不是现有的语法。
所以我目前正在将其实现为:
SELECT *
FROM A
JOIN B1 ON A.b1 = B1.id
JOIN B2 ON B1.b2 = B2.id
LEFT JOIN (SELECT *
FROM C1
JOIN C2 ON C1.c2 = C2.id) AS C ON A.c1 = C.c1
要么有观点。
这就像一个魅力,允许我明确地表达哪个 JOIN 与哪个 JOIN 以及它们的优先级,但是它写起来很重,读起来也很重,也有点冗余。
但是我错过了另一个干净的解决方案吗?
测试集:
DROP TABLE IF EXISTS A;
CREATE TABLE A (b1 int, c1 int);
DROP TABLE IF EXISTS B1;
CREATE TABLE B1 (id int, b2 int);
DROP TABLE IF EXISTS B2;
CREATE TABLE B2 (id int);
DROP TABLE IF EXISTS C1;
CREATE TABLE C1 (id int, c2 int);
DROP TABLE IF EXISTS C2;
CREATE TABLE C2 (id int);
INSERT INTO C2 VALUES (1), (2), (3); -- To remove to make join fail.
INSERT INTO C1 VALUES (1, 1), (2, 2), (3, 3);
INSERT INTO B2 VALUES (1), (2), (3);
INSERT INTO B1 VALUES (1, 1), (2, 2), (3, 3);
INSERT INTO A VALUES (1, 1), (2, 2), (3, 3);
最佳答案
这是括号连接的正确语法:
SELECT *
FROM A
JOIN B1 ON A.b1 = B1.id
JOIN B2 ON C1.b2 = B2.id
LEFT JOIN
(C1 JOIN C2 ON C1.c2 = C2.id)
ON A.c1 = C1.id
想一想您将如何在熟悉的算术语法中使用括号。你不会写:
A * B1 * B2 (* C1 * C2)
你会写:
A * B1 * B2 * (C1 * C2)
也就是说,乘法运算符是一个二元运算符,所以它有两个操作数,一个左,一个右。操作数可以是术语或带括号的子表达式。但是子表达式必须遵循相同的规则,其中乘法仍然是二元运算符。您不能将二元运算符放在表达式的左端。
关于mysql - 强制 INNER JOIN/LEFT JOIN 优先级和组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42813207/