我有一堆表让我们说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。
但是如果LEFT JOIN C2
失败,我也希望“C”的分支失败(在这种情况下我不想要来自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);
答案 0 :(得分: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)
即,乘法运算符是二元运算符,因此它有两个操作数,左和右。操作数可以是术语或带括号的子表达式。但是子表达式必须遵循相同的规则,其中乘法仍然是二元运算符。你不能将二元运算符放在表达式的左端。
答案 1 :(得分:0)
据我所知
SELECT *
FROM A
INNER JOIN (B1,B2)
ON A.b1 = B1.id
AND C1.b2 = B2.id
LEFT JOIN (C1,C2)
ON A.c1 = C1.id
AND C1.c2 = C2.id)
会按预期工作
SELECT ... FROM (t1,t2) WHERE ... is the same as t1 INNER JOIN t2
上面的例子工作“喜欢”INNER JOIN,事实上因为我知道它是CROSS JOIN,这略有不同......但直到现在我才知道真正的区别是什么,也许有人可以告诉我们;)
直到那时,示例obove应该适合你
答案 2 :(得分:0)
我目前的解决方案是创建一个类似的视图:
CREATE OR REPLACE VIEW VC AS
SELECT C1.id AS c1_id, C2.id AS c2_id
FROM C1
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 VC ON VC.c1_id = A.c1;
它使解决方案可读,并且视图可以在其他查询中重用,这很好。