最近在使用Hive中,遇到了一个隐式转换的坑。
首先看一下两个表格
table1
order_number(type:string) | value |
150970594253582620 | 123 |
table2
order_number(type:bigint) | value |
150970594253582621 | 123 |
在两个表的使用中,需要对两个表进行连接
SELECT
oi.order_number order1,
cc.order_number order2
from dw.table1 a
join dw.table2 b
on a.order_number = b.order_number
按理说两条数据是不会进行连接,结果却跟想象的不同
order1 | order2 |
150970594253582620 | 150970594253582621 |
What !?
原因是table1的order_number和table2的order_number一个是string,一个是bigint。在string和bigint连接时,都会隐式转换成double。
其中bigint的精度为19位,大小是8byte,范围是-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807。
其中double的精度为15或16位,大小是8byte,范围是-1.7976E+308 ~ 1.797693E+308。
由此,两者都会损失精度,造成两者相等的情况。
所以在比较bigint和string的时候要显示的指定两者的类型。
另一种情况,hive在比较date和string时,date_add会转换成string类型
'2020-09-11 00:00:00' > date_add('2020-09-12', -1)
结果是true
他们的最终比较是
'2020-09-11 00:00:00' > '2020-09-11'
比较的字符串结果为true
但是,随着hive版本的提升,从0.13开始支持date类型,date_add会转换成date类型,两者比较时都会转换成date类型,即
'2020-09-11' > '2020-09-11'
结果是false
同Java语言一样,Hive也包括隐式转换(implicit conversions)和显式转换(explicitly conversions)。
Hive在需要的时候将会对numeric类型的数据进行隐式转换。比如我们对两个不同数据类型的数字进行比较,假如一个数据类型是INT型,另一个是SMALLINT类型,那么SMALLINT类型的数据将会被隐式转换地转换为INT类型,这个到底和Java中的一样;但是我们不能隐式地将一个 INT类型的数据转换成SMALLINT或TINYINT类型的数据,这将会返回错误,除非你使用了CAST操作。
任何整数类型都可以隐式地转换成一个范围更大的类型。TINYINT,SMALLINT,INT,BIGINT,FLOAT和STRING都可以隐式地转换成DOUBLE;是的你没看出,STRING也可以隐式地转换成DOUBLE!但是你要记住,BOOLEAN类型不能转换为其他任何数据类型!如果强转换的话会返回NULL。