在 MySQL 中模拟 FULL OUTER JOIN 时如何正确组合多个 WHERE 语句和多个 ON 子句

How to correctly combine multiple WHERE statements and multiple ON clauses when emulating a FULL OUTER JOIN in MySQL

我有两张桌子。全球渔业数据(捕捞和水产养殖)。我想通过在 MySQL 中模拟 FULL OUTER JOIN 来组合。

Tbl_A - 捕获

Tbl_B - 水产养殖

这很复杂:

Tbl_A - 捕获

cap_id| yr_c| sp_c| iso_c| area_c| qty_c
     3| 2015|  TRR|    54|      8|   120
   678| 2015|  BOM|    62|     27|   0.0
    20| 2015|  TRR|    54|     27|   0.0
    45| 2015|  FRC|     7|     15| 86800

Tbl_B - 水产养殖

cap_id| yr_a| sp_a| iso_a| area_a| qty_a
    78| 2015|  OTS|    32|     27|  6868
   333| 2015|  FRC|     7|     15|   550
   789| 2015|  TRR|    54|     27| 45000
   987| 2015|  TRR|    32|     27|    40

对于选定的年份 (2015),我正在尝试捕获:

  1. Tbl_A & Tbl_B记录其中(物种,iso_code,面积)相同;
  2. Tbl_A 没有 Tbl_B 匹配的记录(物种,iso_code,地区);和
  3. Tbl_B 条记录(物种、iso_code、区域)没有 Tbl_A 匹配项。

Tbl_C - 期望的最终 Tbl

id| cap_id| aqua_id| yr_c| yr_a| sp_c| sp_a| iso_c| iso_a|area_c|area_a| qty_c| qty_a 

1 |     20|     789| 2015| 2015|  TRR|  TRR|    54|    54|    27|    27|   0.0| 45000
2 |     45|     333| 2015| 2015|  FRC|  FRC|     7|     7|    15|    15| 86800| 550
3 |    678|    NULL| 2015| NULL|  BOM| NULL|    62|  NULL|    27|  NULL|   0.0| NULL
4 |      3|    NULL| 2015| NULL|  TRR| NULL|    54|  NULL|     8|  NULL|   120| NULL
5 |   NULL|      78| NULL| 2015| NULL|  OTS|  NULL|    32|  NULL|    27|  NULL| 6868    
6 |   NULL|     987| NULL| 2015| NULL|  TRR|  NULL|    32|  NULL|    27|  NULL| 40

我有一个使用 UNION 连接两个 LEFT JOINS 的查询:

(SELECT 
c.capture_id,
a.aqua_id,
c.year_c,
a.year_a,
c.species_c,
a.species_a,
c.iso_code_c,
a.iso_code_a,
c.area_c,
a.area_a,
c.environ_code_c,
a.environ_code_a,
c.qty_taken,
a.qty_prod
FROM capture AS c 
LEFT JOIN aquaculture AS a 
ON c.year_c = a.year_a AND c.iso_code_c = a.iso_code_a AND c.area_c = a.area_a AND c.species_c = 
a.species_a
WHERE c.year_c = 2015 AND a.year_a = 2015)
UNION
(SELECT 
c.capture_id,
a.aqua_id,
c.year_c,
a.year_a,
c.species_c,
a.species_a,
c.iso_code_c,
a.iso_code_a,
c.area_c,
a.area_a,
c.qty_taken,
a.qty_prod
FROM  aquaculture AS a
LEFT JOIN capture AS c 
ON c.year_c = a.year_a AND c.iso_code_c = a.iso_code_a AND c.area_c = a.area_a AND c.species_c = a.species_a
WHERE a.year_a = 2015 AND c.year_c = 2015);

但上面的查询只返回一小部分匹配记录

id| cap_id| aqua_id| yr_c| yr_a| sp_c| sp_a| iso_c| iso_a|area_c|area_a| qty_c| qty_a 

1 |     20|     789| 2015| 2015|  TRR|  TRR|    54|    54|    27|    27|   0.0| 45000
2 |     45|     333| 2015| 2015|  FRC|  FRC|     7|     7|    15|    15| 86800|   550

我不明白我是如何抵消 LEFT JOINS 的效果的

由于 MySQL 仅支持左、右和内连接 - 您需要编写两个查询:1) table A 左连接 table B 2) table B left join table A。然后在UNION的帮助下将它们合并为一个结果。 Union 还会删除结果中的重复行,因此结果集中只有 3 种类型的行:

  1. 包含来自两个 table 的数据的行,即 A 内连接 B
  2. 包含来自 table A 的数据的行,其中没有来自 B 的匹配项。即 A 左连接 B
  3. 包含来自 table B 的数据的行,其中 A 中没有匹配项,即 B 离开加入 A

尝试:

SELECT ...
FROM c
LEFT JOIN a ON ...
UNION
SELECT ...
FROM a
LEFT JOIN c ON ...

您的问题出在 WHERE 子句中。您正在排除 'RIGHT' table 记录为空的记录。

SELECT *
FROM c LEFT JOIN a ON ...
WHERE c.year = 2015 /*remove AND a.year = 2015*/
UNION SELECT *
FROM a LEFT JOIN c ON ...
WHERE a.year = 2015 /*remove AND c.year = 2015*/