BigQuery开平方计算遇负值报错 如何将负值置为0处理
实现方法
可以直接通过BigQuery内置函数实现目标兜底逻辑,无需自定义复杂判断。
报错根因说明
BigQuery中POWER(x, 0.5)是算术平方根计算,对小于0的入参直接抛出执行错误,不会自动返回空值或默认值,必须在计算平方根前对入参做非负兜底。
核心实现逻辑
使用GREATEST()函数对开平方的入参做截断处理:
- 该函数会返回所有传入参数的最大值,将待开平方的表达式和0同时传入函数
- 当表达式计算结果≥0时,直接返回原计算值参与后续运算
- 当表达式计算结果<0时,自动返回0作为开平方的入参,从根源上避免负数触发的报错
可直接替换的原查询修改方案
如果不想改动原有UPDATE的整体结构,只需要定位到原语句中触发报错的POWER段,替换成带GREATEST兜底的写法即可,不需要调整其他逻辑:
UPDATE `table` SET SW_FERTL = CASE WHEN POR_CLEAN < 0.04 THEN 1 WHEN (1/((rho_matrix-RHOB)/(rho_matrix-rho_mud_filt)))*POWER(GREATEST(((RW/ILD)+(POWER((0.3*VSHALE/2), 2)-(0.3*VSHALE/2))), 0), 0.5) > 1 THEN 1 ELSE (1/((rho_matrix-RHOB)/(rho_matrix-rho_mud_filt)))*POWER(GREATEST(((RW/ILD)+(POWER((0.3*VSHALE/2), 2)-(0.3*VSHALE/2))), 0), 0.5) END WHERE DEPTH_M IS NOT NULL
优化版查询说明
原语句中重复书写了两次完全一致的长计算逻辑,不仅增加了计算开销,后续如果调整公式很容易出现两处计算逻辑不一致的问题。可以通过提前提取公共计算字段的方式优化:
UPDATE `table` SET SW_FERTL = CASE WHEN POR_CLEAN < 0.04 THEN 1 WHEN porosity_factor * sqrt_term > 1 THEN 1 ELSE porosity_factor * sqrt_term END FROM ( SELECT DEPTH_M, -- 公共计算字段:孔隙度校正系数 1/((rho_matrix-RHOB)/(rho_matrix-rho_mud_filt)) AS porosity_factor, -- 公共计算字段:带兜底的平方根计算结果 POWER( GREATEST( (RW/ILD)+(POWER((0.3*VSHALE/2), 2)-(0.3*VSHALE/2)), 0 ), 0.5 ) AS sqrt_term FROM `table` WHERE DEPTH_M IS NOT NULL ) AS calc WHERE `table`.DEPTH_M = calc.DEPTH_M
补充说明:如果偏好使用CASE语句实现同样的兜底逻辑,效果和GREATEST完全一致,只是写法更冗长,需要重复写入待判断的长表达式:
POWER(CASE WHEN ((RW/ILD)+(POWER((0.3*VSHALE/2), 2)-(0.3*VSHALE/2))) < 0 THEN 0 ELSE ((RW/ILD)+(POWER((0.3*VSHALE/2), 2)-(0.3*VSHALE/2))) END, 0.5)
内容的提问来源于stack exchange,提问作者daniellidio
相关产品推荐
相关产品推荐

