首页 > 解决方案 > Hive - Parquet 格式 - OR 子句在未按预期工作的地方

问题描述

我正在创建一个表并插入如下数据

CREATE TABLE `mydb.mytable`(
  `seq_num` decimal(18,0),
  `ins_upd_flag` char(1)
  )
stored as parquet;

INSERT OVERWRITE TABLE mydb.mytable
SELECT 10457 SEQ_NUM,'I' INS_UPD_FLAG UNION ALL 
SELECT 10462,'I' UNION ALL 
SELECT 10461,'I' UNION ALL 
SELECT 10460,'I' UNION ALL 
SELECT 10459,'I' UNION ALL 
SELECT 10456,'I' UNION ALL 
SELECT 10458,'I';

正如您在上面看到的,第二列值只是“I”,它没有任何额外的字符。

当我运行以下查询时,它不会产生任何结果

SELECT T.*, length(INS_UPD_FLAG), length(trim(INS_UPD_FLAG))
FROM mydb.mytable T
WHERE SEQ_NUM <> 0  OR INS_UPD_FLAG <> 'I' ;

但是,如果我运行以下查询,它将按预期返回所有插入的行

SELECT T.*, length(INS_UPD_FLAG), length(trim(INS_UPD_FLAG)) -- both length =1
FROM mydb.mytable T
WHERE SEQ_NUM <> 0 OR TRIM(INS_UPD_FLAG) <> 'I' ;

关于为什么会发生这种情况以及如何解决的任何解释?我需要不使用修剪的结果

请注意,此问题仅在 OR 条件下发生。如果我运行以下查询,我会得到结果

SELECT T.*, length(INS_UPD_FLAG), length(trim(INS_UPD_FLAG))
FROM mydb.mytable T
WHERE SEQ_NUM <> 0 and  INS_UPD_FLAG = 'I' ;

此外,如果我使用 ORC 或文本格式创建表格,我会得到没有修剪的结果。

标签: hivehiveqlhadoop2

解决方案


我设法重新解决了您的问题并获得了与您解释的相同的结果。

我运行了一个查询,看看你的 where 条件到底是什么:

SELECT
  T.*,
  length(INS_UPD_FLAG),
  length(trim(INS_UPD_FLAG)),
  SEQ_NUM <> 0,
  INS_UPD_FLAG = 'I',
  SEQ_NUM <> 0 or INS_UPD_FLAG = 'I'
FROM mydb.mytable T

结果如下:

|seq_num|ins_upd_flag|_c1|_c2|_c3 |_c4 |_c5 |
|10457  |I           |1  |1  |true|true|true|
|10462  |I           |1  |1  |true|true|true|
|10461  |I           |1  |1  |true|true|true|
|10460  |I           |1  |1  |true|true|true|
|10459  |I           |1  |1  |true|true|true|
|10456  |I           |1  |1  |true|true|true|
|10458  |I           |1  |1  |true|true|true|

如您所见,它正在返回true您的加入条件。

出于好奇,我将 where 条件包裹起来(),得到了没有修剪的结果。

SELECT
  T.*,
  length(INS_UPD_FLAG),
  length(trim(INS_UPD_FLAG)),
  SEQ_NUM <> 0,
  INS_UPD_FLAG = 'I',
  SEQ_NUM <> 0 or INS_UPD_FLAG = 'I'
FROM mydb.mytable T
where (SEQ_NUM <> 0 or INS_UPD_FLAG = 'I')

结果:与之前的查询相同。

我通过 Hue 2.6.1-227 使用 Hive 1.2.1000。

我不知道魔术()在做什么以及为什么没有它查询就无法工作。


推荐阅读