为啥当缺少连接字段之一时,HIVE 中的完全外部连接会给出奇怪的结果?
Posted
技术标签:
【中文标题】为啥当缺少连接字段之一时,HIVE 中的完全外部连接会给出奇怪的结果?【英文标题】:Why does full outer join in HIVE gives weird result when one of the join fields is missing?为什么当缺少连接字段之一时,HIVE 中的完全外部连接会给出奇怪的结果? 【发布时间】:2016-10-14 20:00:32 【问题描述】:我正在比较 SQL 引擎之间的行为。 Oracle 具有我所期望的 SQL 引擎完全外连接的行为:
甲骨文
CREATE TABLE sql_test_a
(
ID VARCHAR2(4000 BYTE),
FIRST_NAME VARCHAR2(200 BYTE),
LAST_NAME VARCHAR2(200 BYTE)
);
CREATE TABLE sql_test_b
(
NUM VARCHAR2(4000 BYTE),
FIRST_NAME VARCHAR2(200 BYTE),
LAST_NAME VARCHAR2(200 BYTE)
);
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('1', 'John', 'Snow');
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('2', 'Mike', 'Tyson');
INSERT INTO sql_test_b (NUM, FIRST_NAME, LAST_NAME) VALUES ('20', 'Mike', 'Tyson');
当我执行以下操作时,它给了我预期的结果。结果表包含两行,其中一行包含NULL
的NUM
字段,因为表sql_test_b
中没有john snow。
SELECT A.FIRST_NAME, A.LAST_NAME, A.ID, B.NUM
FROM
SQL_TEST_A A
FULL OUTER JOIN
SQL_TEST_B B
ON
A.FIRST_NAME = B.FIRST_NAME
AND
A.LAST_NAME = B.LAST_NAME;
你可以在这里测试sql脚本:http://sqltest.net/
蜂巢
但是,在 HIVE 中,如果您要尝试相同的操作,则完全外连接会生成一个包含两行的表。应该是“John Snow”行的行包含字段 FIRST_NAME、LAST_NAME 和 NUM 的 NULL
。 1
填写为ID
,仅此而已。
为什么在 HIVE 中有这种奇怪的行为?这是一个错误吗?或者我错过了什么...因为 Oracle 11g 似乎处理得更好。谢谢。
【问题讨论】:
【参考方案1】:我无法模拟@Candic3 报告的结果
我使用了以下语句以及与问题中相同的“选择”查询。
CREATE TABLE IF NOT EXISTS sql_test_a (ID String, FIRST_NAME String, LAST_NAME String) COMMENT 'sql_test_a'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
CREATE TABLE IF NOT EXISTS sql_test_b (NUM String, FIRST_NAME String, LAST_NAME String) COMMENT 'sql_test_b'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
INSERT INTO sql_test_a VALUES ('1', 'John', 'Snow');
INSERT INTO sql_test_a VALUES ('2', 'Mike', 'Tyson');
INSERT INTO sql_test_b VALUES ('20', 'Mike', 'Tyson');
SELECT A.FIRST_NAME, A.LAST_NAME, A.ID, B.NUM
FROM
SQL_TEST_A A
FULL OUTER JOIN
SQL_TEST_B B
ON
A.FIRST_NAME = B.FIRST_NAME
AND
A.LAST_NAME = B.LAST_NAME;
请查看附件中的结果。
但是,由于未注意到的小错误,例如 DDL 与实际数据(例如,来自平面文件)之间的数据类型不匹配或 DDL 中提到的分隔符与实际数据中的分隔符不匹配,选择查询将返回 NULL .
【讨论】:
【参考方案2】:我认为“(”之后的问题与传统 sql 略有不同。
SELECT A.FIRST_NAME, A.LAST_NAME, A.ID, B.NUM
FROM
SQL_TEST_A A
FULL OUTER JOIN
SQL_TEST_B B ON
(A.FIRST_NAME = B.FIRST_NAME AND A.LAST_NAME = B.LAST_NAME);
【讨论】:
【参考方案3】:在选择语句中,您使用了 A.FIRST_NAME、A.LAST_NAME,这对于表 B 中的行不存在。这就是 null 值的原因。而是使用 COALESCE 在 A.FIRST_NAME 和 B.FIRST_NAME 之间查找非空值
SELECT COALESCE(A.FIRST_NAME, B.FIRST_NAME) as FIRST_NAME, COALESCE(A.LAST_NAME, B.LAST_NAME) as LAST_NAME, A.ID, B.NUM
FROM
SQL_TEST_A A
FULL OUTER JOIN
SQL_TEST_B B
ON
A.FIRST_NAME = B.FIRST_NAME
AND
A.LAST_NAME = B.LAST_NAME;
【讨论】:
以上是关于为啥当缺少连接字段之一时,HIVE 中的完全外部连接会给出奇怪的结果?的主要内容,如果未能解决你的问题,请参考以下文章
当单个字段是 GROUP BY 中的多个字段之一时,如何汇总该字段的数据?
当 UDF 使用一些外部资源文件但在本机运行时,为啥 Hive 错误 FileNotFoundException?