Question

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='提转统计';
Was it helpful?

Solution

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;

OTHER TIPS

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;
Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top