【问题标题】:Why does MySQL report a syntax error on FULL OUTER JOIN?为什么 MySQL 会在 FULL OUTER JOIN 上报告语法错误?
【发布时间】:2011-01-23 23:12:08
【问题描述】:
SELECT airline, airports.icao_code, continent, country, province, city, website 

FROM airlines 
FULL OUTER JOIN airports ON airlines.iaco_code = airports.iaco_code
FULL OUTER JOIN cities ON airports.city_id = cities.city_id
FULL OUTER JOIN provinces ON cities.province_id = provinces.province_id
FULL OUTER JOIN countries ON cities.country_id = countries.country_id
FULL OUTER JOIN continents ON countries.continent_id = continents.continent_id

上面写着

您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取正确的语法,以便在航司.iaco_code = airports.iaco_code 上的 'outer join airports 附近使用 第 4 行的全外连接

语法对我来说很合适。我以前从未做过很多连接,但我需要一个表中的这些列,这些列由各种 id 交叉引用。

【问题讨论】:

标签: mysql sql join mysql-error-1064


【解决方案1】:

MySQL 中没有FULL OUTER JOIN。见7.2.12. Outer Join Simplification12.2.8.1. JOIN Syntax

您可以使用 FULL OUTER JOIN 模拟 UNION(从 MySQL 4.0.0 开始):

有两个表t1,t2:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

三个表 t1、t2、t3:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t2.id = t3.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t2.id = t3.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
RIGHT JOIN t3 ON t2.id = t3.id

【讨论】:

  • 有没有关于连接的教程推荐?
  • 您的答案并不完全正确,请参阅Xelrach's answerthis comment
  • @Cletus,我在他们共享的 PK 列上不断收到“列名重复”错误...
【解决方案2】:

cletus 的回答不太正确。 UNION 将删除 FULL OUTER JOIN 将包含的重复记录。如果您需要重复使用类似的东西:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t2.id = t3.id
LEFT JOIN t4 ON t3.id = t4.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t2.id = t3.id
LEFT JOIN t4 ON t3.id = t4.id
WHERE t1.id IS NULL
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
RIGHT JOIN t3 ON t2.id = t3.id
LEFT JOIN t4 ON t3.id = t4.id
WHERE t2.id IS NULL
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
RIGHT JOIN t3 ON t2.id = t3.id
RIGHT JOIN t4 ON t3.id = t4.id
WHERE t3.id IS NULL;

【讨论】:

  • 请注意 - 如果你足够迂腐和理论 - 这也不是一个完美的解决方案。这种方法(使用UNION ALL,但检查JOINed 表之一中的一列是否为NULL 以识别它不能与其他表中的任何行匹配)依赖于实际具有的表至少一个NOT NULL 列。如果没有保证列实际上不包含NULL,则此方法将不起作用。
  • @MarkAmery:你提出了一个很好的观点。为了使反连接正常工作,WHERE 子句中的谓词需要引用我们知道(我们是保证)的列或表达式,如果满足以下条件,则不会为 NULL找到匹配的行。在使用 相等 比较的连接谓词的特殊情况下,该相等比较向我们保证该列的值对于匹配的行不会为 NULL。不必进行相等比较即可为我们提供保证。如果连接确实允许“匹配”行的 NULL 值,我们必须找到/使用非 NULL 表达式。
  • @MarkAmery:此查询不依赖于具有 NOT NULL 列的表。相反,此查询依赖于连接谓词(ON 子句中的条件)来保证“匹配”行中的列的非 NULL 值。这依赖于 相等比较 运算符与 NULL 值一起使用时的行为。 (我们知道foo = NULL 不会返回TRUE,即使foo IS NULL。)
  • 希望mysql能加这个。可能只有 5 行 C 代码。我们每个人都必须多次编写这 5 行额外的代码。使用 mysql 的人看到这应该将其视为功能请求。
【解决方案3】:

需要FULL OUTER JOIN三个表t1、t2、t3的时候就补充一下。您可以依次将 t1、t2、t3 左连接其余两个表,然后联合。

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t1.id = t3.id
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id
LEFT JOIN t3 ON t2.id = t3.id
UNION
SELECT * FROM t3
LEFT JOIN t1 ON t3.id = t1.id
LEFT JOIN t2 ON t3.id = t2.id

【讨论】:

    【解决方案4】:

    我刚刚为此做了一个技巧:

    (select 1 from DUAL) d
    LEFT OUTER JOIN t1 ON t1.id = t2.id
    LEFT OUTER JOIN t2 ON t1.id = t2.id
    

    关键是,来自 dual 的查询是一个固定点,mysql 可以将其他 2 个表外部连接到该点

    【讨论】:

    • 但此时未声明t2JOIN t1 ON t1.id = t2.id
    猜你喜欢
    • 2012-09-10
    • 2021-03-31
    • 2013-01-09
    • 2011-03-14
    • 2021-09-06
    相关资源
    最近更新 更多