为啥 MySQL 会在 FULL OUTER JOIN 上报告语法错误?
Posted
技术标签:
【中文标题】为啥 MySQL 会在 FULL OUTER JOIN 上报告语法错误?【英文标题】: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 交叉引用。
【问题讨论】:
没有FULL OUTER JOIN
语法:dev.mysql.com/doc/refman/5.0/en/join.html
【参考方案1】:
MySQL 中没有FULL OUTER JOIN
。见7.2.12. Outer Join Simplification和12.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 answer 或this 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
,但检查JOIN
ed 表之一中的一列是否为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 个表外部连接到该点
【讨论】:
但此时未声明t2
:JOIN t1 ON t1.id = t2.id
。以上是关于为啥 MySQL 会在 FULL OUTER JOIN 上报告语法错误?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MySQL 中进行 FULL OUTER JOIN?
如何在 MySQL 中进行 FULL OUTER JOIN?
如何在 MySQL 中进行 FULL OUTER JOIN?
MySQL:FULL OUTER JOIN - 如何合并一列?