mysql - 强制 INNER JOIN/LEFT JOIN 优先级和组

标签 mysql join subquery mariadb

我有一堆表,比方说 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/

相关文章:

mysql - 子查询不访问父查询别名

jquery - 隐藏空数据库表列

mysql - Django ORM - 具有不同选择子句的分组聚合

mysql - 为什么基于 SELECT 的 DELETE 不能与 mysql 5.0 一起使用

mysql - 数据库中的运动跟踪

android - CursorLoader - 两个表连接查询?

mysql,使用 WHERE 子句连接多个表

MySQL join child + parent 在同一个表中,然后将两者与另一个表连接

MySQL ...根据查询另一个表从表中删除记录

mysql - 如何将这段sql翻译成没有子查询的左连接?