Hive中浮点数比较踩过的坑

疑问案例:

查询员工表中薪水的减免税超过0.2(20%)的数据:

select name, salary, deductions from employees where deductions > 0.2;

查询结果:

John 100000.0 0.2
Mary 80000.0 0.2

Tom 200000.0 0.3
Fred 150000.0 0.3

为什么deductions = 0.2 的记录也被输出了?


原因:

浮点数float和double在比较的过程中,存在float转化为double进行比较的过程,在float --> double中会出现0.2的最近似的精确值略大于0.2的情况。

这个问题并非仅仅存在于Hive中,Java也存在此问题。

这是所有使用IEEE标准进行浮点数编码的系统中,普遍存在的一个问题。

0.2对于float 类型是0.2000001,而对于double类型是0.200000000001。

这是因为一个8字节的double值具有更多的小数位(小数点后的位数)。当表中的float值通过Hive转换为double值时,其产生的double值是0.200000100000,这个值实际要比0.200000000001大,这就是为什么查询结果像是使用了 >= 而不是 > 了。


对于上述问题的规避方法:

使用cast操作符显式地指出0.2是float类型。

cast语法:cast( 数值 as float )

select name, salary, deductions from employees where deductions > cast(0.2 as float);
Hive 中,虽然没有专门用于比较两个字段大小的函数(如 `COMPARE()`),但可以使用标准 SQL 比较运算符和一些内置函数来实现类似功能。以下是几种常见的方法: ### 1. 使用比较操作符 Hive 支持常见的比较操作符来比较两个列的值: - `>`:判断左侧列是否大于右侧列 - `<`:判断左侧列是否小于右侧列 - `=`:判断两个列是否相等 - `>=` 和 `<=`:分别表示“大于等于”和“小于等于” - `<>` 或 `!=`:不等于 例如,查询某个表中 `col1 > col2` 的记录: ```sql SELECT * FROM table_name WHERE col1 > col2; ``` ### 2. 使用 `CASE WHEN` 表达式进行条件判断 如果需要根据两个字段的大小关系返回不同的结果标签,可以使用 `CASE WHEN` 表达式: ```sql SELECT col1, col2, CASE WHEN col1 > col2 THEN 'col1 is greater' WHEN col1 < col2 THEN 'col2 is greater' ELSE 'equal' END AS comparison_result FROM table_name; ``` ### 3. 使用 `GREATEST` 和 `LEAST` 函数 Hive 提供了 `GREATEST` 和 `LEAST` 函数,可用于从多个列或表达式中选择最大值或最小值 [^1]。 - `GREATEST(col1, col2)` 返回两列中的较大值。 - `LEAST(col1, col2)` 返回两列中的较小值。 例如: ```sql SELECT col1, col2, GREATEST(col1, col2) AS max_value, LEAST(col1, col2) AS min_value FROM table_name; ``` 这些函数适用于整数、浮点数、字符串等多种数据类型,并且支持多参数输入。 ### 4. 使用 `SIGN` 函数结合数学计算 若希望以数值形式表示比较结果(如 1 表示大于,-1 表示小于,0 表示相等),可以使用以下方式: ```sql SELECT col1, col2, CASE WHEN col1 - col2 > 0 THEN 1 WHEN col1 - col2 < 0 THEN -1 ELSE 0 END AS compare_code FROM table_name; ``` 或者使用 `SIGN` 函数简化该逻辑: ```sql SELECT col1, col2, SIGN(col1 - col2) AS compare_sign FROM table_name; ``` `compare_sign` 的取值含义如下: - `1`:`col1 > col2` - `-1`:`col1 < col2` - `0`:`col1 = col2` ### 5. 自定义 UDF 实现复杂比较逻辑 对于更复杂的比较需求,例如对自定义类型进行比较,可以通过编写 Hive UDF 来扩展功能。UDF 需要将 Java 类打包为 JAR 文件并注册到 Hive 环境中 [^5]。 例如,创建一个临时 UDF 并使用它进行比较: ```sql ADD JAR /path/to/your_udf.jar; CREATE TEMPORARY FUNCTION custom_compare AS 'com.example.CustomCompareUDF'; -- 使用 UDF 进行比较 SELECT col1, col2, custom_compare(col1, col2) FROM table_name; ``` ### 6. 处理 NULL 值的情况 当涉及 NULL 值时,Hive比较行为遵循 SQL 标准&mdash;&mdash;任何与 NULL 的比较都会返回 NULL。为了处理这种情况,可以使用 `COALESCE` 函数提供默认值: ```sql SELECT COALESCE(col1, 0), COALESCE(col2, 0), GREATEST(COALESCE(col1, 0), COALESCE(col2, 0)) AS safe_max FROM table_name; ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值