How to handle divide by zero in GENERATED columns in MySQL
-
14-03-2021 - |
Frage
I am using GENERATED AS
columns in MySQL 5.7 as follows:
ALTER TABLE report_user
MODIFY avg_trans_out_amount bigint
GENERATED ALWAYS AS (round(trans_out_amount/(trans_out_count))) STORED;
but sometimes the trans_out_count
could be 0, then the GENERATED AS
column will give a divide by zero error. So, what I did was:
ALTER TABLE report_user
MODIFY avg_trans_out_amount bigint
GENERATED ALWAYS AS (round(trans_out_amount/(trans_out_count + 0.00001))) STORED;
but can be a little problematic - for example for 100,000/1.00001
, the right value is 100,000, but the actual value it not correct 9,999.90
. What should I do to handle this problem? This is the table DML:
CREATE TABLE `report_user` (
`trans_into_count` int(11) NOT NULL DEFAULT '0' COMMENT '转入次数',
`trans_out_count` int(11) NOT NULL DEFAULT '0' COMMENT '转出次数',
`trans_into_amount` bigint(11) NOT NULL DEFAULT '0' COMMENT '转入金额',
`trans_out_amount` bigint(11) NOT NULL DEFAULT '0' COMMENT '转出金额',
`avg_trans_into_amount` bigint(20) GENERATED ALWAYS AS (round((`trans_into_amount` / (`trans_into_count` + 0.00001)),0)) STORED,
`avg_trans_out_amount` bigint(20) GENERATED ALWAYS AS (round((`trans_out_amount` / (`trans_out_count` + 0.00001)),0)) STORED,
`user_name` varchar(256) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '用户名',
`user_id` bigint(20) NOT NULL COMMENT '用户ID'
) ENGINE=InnoDB AUTO_INCREMENT=36149 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='提转统计';
Lösung
There are three ways to handle DIVIDE BY ZERO
error in your case :
1) USING
IF()
:
ALTER TABLE report_user
modify avg_trans_out_amount bigint
GENERATED ALWAYS AS (round(trans_out_amount/if(trans_out_count,0,1))) STORED;
2) USING
NULLIF()
:
ALTER TABLE report_user
modify avg_trans_out_amount bigint
GENERATED ALWAYS AS (round(trans_out_amount/nullif(trans_out_count,1))) STORED;
3) USING
GREATEST()
:
ALTER TABLE report_user
MODIFY avg_trans_out_amount bigint
GENERATED ALWAYS AS (round(trans_out_amount/greatest(trans_out_count,1))) STORED;
Andere Tipps
aready tried out, I am using this sql to solve my problem:
ALTER TABLE report_user
MODIFY avg_trans_out_amount bigint
GENERATED ALWAYS AS (
round(trans_out_amount/(case when trans_out_count=0 then 1 else trans_out_count end))
) STORED;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange