MYSQL FULL OUTER JOIN - 使用 LEFT-UNION-LEFT JOIN 时所有 NULL 结果
MYSQL FULL OUTER JOIN - All NULL results when using LEFT-UNION-LEFT JOIN
Tbl_A
cap_id| yr_a| sp_a| iso_a| area_a| qty_a | prod_a |
3| 2015| TRR| 54| 8| 120 | 0 |
678| 2015| BOM| 62| 27| 0.0 | 0 |
20| 2015| TRR| 54| 27| 0.0 | 0 |
45| 2015| FRC| 7| 15| 86800 | 0 |
52| 2015| AZB| 12| 6| 987 | 0 |
Tbl_B
aqua_id| yr_b| sp_b| iso_b| area_b| qty_b | prod_b |
78| 2015| OTS| 32| 27| 6868 | 1 |
333| 2015| FRC| 7| 15| 550 | 1 |
334| 2015| FRC| 7| 15| 550 | 2 |
789| 2015| TRR| 54| 27| 45000 | 3 |
987| 2015| TRR| 32| 27| 40 | 2 |
我得到了我正在寻找的 FULL OUTER JOIN
但是查询也生成了一大堆所有 NULL 记录(Tbl_C 中的 id 为 7-9)
Tbl_C - 最终表
id| cap_id| aqua_id| yr_a| yr_b| sp_a| sp_b| iso_a| iso_b|area_a|area_b| qty_a| qty_b | prod_a | prod_b
1 | 20| 789| 2015| 2015| TRR| TRR| 54| 54| 27| 27| 0.0| 45000 | 0 | 1
2 | 45| 333| 2015| 2015| FRC| FRC| 7| 7| 15| 15| 86800| 550 | 0 | 1
3 | 45| 334| 2015| 2015| FRC| FRC| 7| 7| 15| 15| 86800| 550 | 0 | 2
4 | 678| NULL| 2015| NULL| BOM| NULL| 62| NULL| 27| NULL| 0.0| NULL | 0 | NULL
5 | 3| NULL| 2015| NULL| TRR| NULL| 54| NULL| 8| NULL| 120| NULL | 0 | NULL
6 | NULL| 78| NULL| 2015| NULL| OTS| NULL| 32| NULL| 27| NULL| 6868 | 0 | 1
7 | NULL| 987| NULL| 2015| NULL| TRR| NULL| 32| NULL| 27| NULL| 40 | 0 | 2
8 | NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL | NULL | NULL
9 | NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL | NULL | NULL
我想弄清楚是什么导致了额外的多个全空记录?
使用的查询是:
(SELECT a.cap_id, b.aqua_id, a.yr_a, b.yr_b,...., a.qty_a, b.qty_b
FROM Tbl A AS a LEFT JOIN Tbl_B AS b
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE a.yr_a = 2015)
UNION
(SELECT a.cap_id, b.aqua_id, a.yr_a, b.yr_b,...., a.qty_a, b.qty_a
FROM Tbl_B AS b LEFT JOIN Tble_A AS a
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE b.yr_b = 2015);
DEMO:http://rextester.com/AWDYA21027 使用您的示例数据和查询,我没有得到重复的空列。这意味着数据问题。
为什么要让它成为左连接?只需从左向右切换并将 where 子句切换为 b.yr_a.
要消除空值,请通过消除所有 4 个值都为空的记录来确保至少匹配一个连接条件?
给定您的示例数据,完整的外部联接将 return:当按 cap_Id 和 aqua_ID
排序时
+--------+---------+------+------+-------+-------+
| CAP_ID | AQUA_ID | YR_A | YR_B | QTY_A | QTY_B |
+--------+---------+------+------+-------+-------+
| | 78 | | 2015 | | 6868 |
| | 987 | | 2015 | | 40 |
| 3 | | 2015 | | 120 | |
| 20 | 789 | 2015 | 2015 | 0 | 45000 |
| 45 | 333 | 2015 | 2015 | 86800 | 550 |
| 678 | | 2015 | | 0 | |
+--------+---------+------+------+-------+-------+
下面的查询 returns:
+----+--------+---------+------+------+----------+----------+
| | cap_id | aqua_id | yr_a | yr_b | qty_a | qty_b |
+----+--------+---------+------+------+----------+----------+
| 1 | NULL | 78 | NULL | 2015 | NULL | 6868,00 |
| 2 | NULL | 987 | NULL | 2015 | NULL | 40,00 |
| 3 | 3 | NULL | 2015 | NULL | 120,00 | NULL |
| 4 | 20 | 789 | 2015 | 2015 | 0,00 | 45000,00 |
| 5 | 45 | 333 | 2015 | 2015 | 86800,00 | 550,00 |
| 6 | 678 | NULL | 2015 | NULL | 0,00 | NULL |
+----+--------+---------+------+------+----------+----------+
这似乎是完整外部联接的正确结果。
如果我在 A 或 B 中有重复值,则此查询 returns 那些重复值,因为 UNION 中的 distinct 没有发生,因为我们正在做一个 union all;不是工会。
(SELECT a.cap_id, b.aqua_id, a.yr_a, b.yr_b, a.qty_a, b.qty_b
FROM tbl_A AS a
LEFT JOIN tbl_B AS b
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE a.yr_a = 2015
and (a.yr_a is not null
or a.iso_a is not null
or a.area_a is not null
or a.sp_a is not null))
UNION ALL
(SELECT a.cap_id, b.aqua_id, a.yr_a, b.yr_b, a.qty_a, b.qty_b
FROM tbl_A AS a
RIGHT JOIN tbl_B AS b
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE b.yr_b = 2015
and (b.yr_b is not null
or b.iso_b is not null
or b.area_b is not null
or b.sp_b is not null)
and a.iso_a is null #to exclude extra nulls duplicated by union all.
);
生成 NULLS 是因为:
在第二个 LEFT JOIN 的 ON 子句变量之一的 WHERE 子句中没有 "IS NULL" INNER JOIN 运行两次!
更糟的是,我将一个较短的 table 加入了一个较长的 Tbl_B < Tbl_A 的行_#,因此 Tbl_b 中不存在所有 Tbl_A 2015 年记录。
答案似乎很简单。
如果你拿第一个 select 和 运行 它:
SELECT a.*, b.*
FROM Tbl_A AS a LEFT JOIN Tbl_B AS b
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE a.yr_a = 2015
您可能应该得到 5 行结果,因为 5 行是 Tbl_A。问题是由于连接标准,并非所有这些行都与 Tbl_B 中的行连接。因此,当您连接这些表时,对于 Tbl_A 的某些行,Tbl_B 的列将是 NULL,因为连接是外部的。
这同样适用于您的第二个查询:
SELECT a.*, b.*
FROM Tbl_B AS b LEFT JOIN Tbl_A AS a
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE b.yr_b = 2015
来自 Tbl_B 的行没有与 Tbl_A 的精确连接,因此自从您离开连接到 B 后,您的 Tbl_B 行将有大量 NULL .
我建议你 运行 一个一个地查看每个查询的结果。
Tbl_A
cap_id| yr_a| sp_a| iso_a| area_a| qty_a | prod_a |
3| 2015| TRR| 54| 8| 120 | 0 |
678| 2015| BOM| 62| 27| 0.0 | 0 |
20| 2015| TRR| 54| 27| 0.0 | 0 |
45| 2015| FRC| 7| 15| 86800 | 0 |
52| 2015| AZB| 12| 6| 987 | 0 |
Tbl_B
aqua_id| yr_b| sp_b| iso_b| area_b| qty_b | prod_b |
78| 2015| OTS| 32| 27| 6868 | 1 |
333| 2015| FRC| 7| 15| 550 | 1 |
334| 2015| FRC| 7| 15| 550 | 2 |
789| 2015| TRR| 54| 27| 45000 | 3 |
987| 2015| TRR| 32| 27| 40 | 2 |
我得到了我正在寻找的 FULL OUTER JOIN
但是查询也生成了一大堆所有 NULL 记录(Tbl_C 中的 id 为 7-9)
Tbl_C - 最终表
id| cap_id| aqua_id| yr_a| yr_b| sp_a| sp_b| iso_a| iso_b|area_a|area_b| qty_a| qty_b | prod_a | prod_b
1 | 20| 789| 2015| 2015| TRR| TRR| 54| 54| 27| 27| 0.0| 45000 | 0 | 1
2 | 45| 333| 2015| 2015| FRC| FRC| 7| 7| 15| 15| 86800| 550 | 0 | 1
3 | 45| 334| 2015| 2015| FRC| FRC| 7| 7| 15| 15| 86800| 550 | 0 | 2
4 | 678| NULL| 2015| NULL| BOM| NULL| 62| NULL| 27| NULL| 0.0| NULL | 0 | NULL
5 | 3| NULL| 2015| NULL| TRR| NULL| 54| NULL| 8| NULL| 120| NULL | 0 | NULL
6 | NULL| 78| NULL| 2015| NULL| OTS| NULL| 32| NULL| 27| NULL| 6868 | 0 | 1
7 | NULL| 987| NULL| 2015| NULL| TRR| NULL| 32| NULL| 27| NULL| 40 | 0 | 2
8 | NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL | NULL | NULL
9 | NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL| NULL | NULL | NULL
我想弄清楚是什么导致了额外的多个全空记录?
使用的查询是:
(SELECT a.cap_id, b.aqua_id, a.yr_a, b.yr_b,...., a.qty_a, b.qty_b
FROM Tbl A AS a LEFT JOIN Tbl_B AS b
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE a.yr_a = 2015)
UNION
(SELECT a.cap_id, b.aqua_id, a.yr_a, b.yr_b,...., a.qty_a, b.qty_a
FROM Tbl_B AS b LEFT JOIN Tble_A AS a
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE b.yr_b = 2015);
DEMO:http://rextester.com/AWDYA21027 使用您的示例数据和查询,我没有得到重复的空列。这意味着数据问题。
为什么要让它成为左连接?只需从左向右切换并将 where 子句切换为 b.yr_a.
要消除空值,请通过消除所有 4 个值都为空的记录来确保至少匹配一个连接条件?
给定您的示例数据,完整的外部联接将 return:当按 cap_Id 和 aqua_ID
排序时+--------+---------+------+------+-------+-------+
| CAP_ID | AQUA_ID | YR_A | YR_B | QTY_A | QTY_B |
+--------+---------+------+------+-------+-------+
| | 78 | | 2015 | | 6868 |
| | 987 | | 2015 | | 40 |
| 3 | | 2015 | | 120 | |
| 20 | 789 | 2015 | 2015 | 0 | 45000 |
| 45 | 333 | 2015 | 2015 | 86800 | 550 |
| 678 | | 2015 | | 0 | |
+--------+---------+------+------+-------+-------+
下面的查询 returns:
+----+--------+---------+------+------+----------+----------+
| | cap_id | aqua_id | yr_a | yr_b | qty_a | qty_b |
+----+--------+---------+------+------+----------+----------+
| 1 | NULL | 78 | NULL | 2015 | NULL | 6868,00 |
| 2 | NULL | 987 | NULL | 2015 | NULL | 40,00 |
| 3 | 3 | NULL | 2015 | NULL | 120,00 | NULL |
| 4 | 20 | 789 | 2015 | 2015 | 0,00 | 45000,00 |
| 5 | 45 | 333 | 2015 | 2015 | 86800,00 | 550,00 |
| 6 | 678 | NULL | 2015 | NULL | 0,00 | NULL |
+----+--------+---------+------+------+----------+----------+
这似乎是完整外部联接的正确结果。 如果我在 A 或 B 中有重复值,则此查询 returns 那些重复值,因为 UNION 中的 distinct 没有发生,因为我们正在做一个 union all;不是工会。
(SELECT a.cap_id, b.aqua_id, a.yr_a, b.yr_b, a.qty_a, b.qty_b
FROM tbl_A AS a
LEFT JOIN tbl_B AS b
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE a.yr_a = 2015
and (a.yr_a is not null
or a.iso_a is not null
or a.area_a is not null
or a.sp_a is not null))
UNION ALL
(SELECT a.cap_id, b.aqua_id, a.yr_a, b.yr_b, a.qty_a, b.qty_b
FROM tbl_A AS a
RIGHT JOIN tbl_B AS b
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE b.yr_b = 2015
and (b.yr_b is not null
or b.iso_b is not null
or b.area_b is not null
or b.sp_b is not null)
and a.iso_a is null #to exclude extra nulls duplicated by union all.
);
生成 NULLS 是因为: 在第二个 LEFT JOIN 的 ON 子句变量之一的 WHERE 子句中没有 "IS NULL" INNER JOIN 运行两次! 更糟的是,我将一个较短的 table 加入了一个较长的 Tbl_B < Tbl_A 的行_#,因此 Tbl_b 中不存在所有 Tbl_A 2015 年记录。
答案似乎很简单。 如果你拿第一个 select 和 运行 它:
SELECT a.*, b.*
FROM Tbl_A AS a LEFT JOIN Tbl_B AS b
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE a.yr_a = 2015
您可能应该得到 5 行结果,因为 5 行是 Tbl_A。问题是由于连接标准,并非所有这些行都与 Tbl_B 中的行连接。因此,当您连接这些表时,对于 Tbl_A 的某些行,Tbl_B 的列将是 NULL,因为连接是外部的。
这同样适用于您的第二个查询:
SELECT a.*, b.*
FROM Tbl_B AS b LEFT JOIN Tbl_A AS a
ON a.yr_a = b.yr_b
AND a.iso_a = b.iso_b
AND a.area_a = b.area_b
AND a.sp_a = b.sp_b
WHERE b.yr_b = 2015
来自 Tbl_B 的行没有与 Tbl_A 的精确连接,因此自从您离开连接到 B 后,您的 Tbl_B 行将有大量 NULL .
我建议你 运行 一个一个地查看每个查询的结果。