【1】问题场景原代码
引起问题的原代码,访问数据库,汇总数据后,使用汇总结果报异常:
1 local function amount_sum_fee(cycleid) 2 local select_productid = "select product_id from np_cdr_" .. cycleid .. " group by product_id;" 3 local rtn, productid_set = executeSql(select_productid) 4 if rtn then 5 local value_count = 0 6 local sum_count = 0 7 local sql_const = "insert into compare_fee_" .. cycleid .. " (product_id, np_id, np_sum_duration, np_total_times, " .. 8 " np_sum_qty, np_sum_fee, un_sum_duration, un_total_times, un_sum_fee, sum_np_fee, sum_original_fee) values " 9 if type(productid_set) == 'table' and next(productid_set) ~= nil then 10 for key, record in pairs(productid_set) do 11 local amount_table = {} 12 amount_table["product_id"] = record["product_id"] 13 amount_table["np_id"] = 'all' 14 -- np总费用统计 15 local np_sum_fee = "SELECT product_id, SUM(duration) AS np_sum_duration, " .. 16 " COUNT(id) AS np_sum_cdrCnt, " .. 17 " SUM(service_qty) AS np_service_qty, " .. 18 " SUM(service_fee) AS np_service_fee, " .. 19 " SUM(np_fee) AS np_sum_fee, " .. 20 " SUM(original_fee) AS np_sum_original_fee " .. 21 " FROM np_cdr_" .. cycleid .. " WHERE product_id = '" .. record["product_id"] .. "';" 22 local rtn, desc = executeSql(np_sum_fee) 23 if rtn and next(desc) ~= nil then 24 amount_table["np_sum_duration"] = desc[1]["np_sum_duration"] 25 amount_table["np_total_times"] = desc[1]["np_sum_cdrCnt"] 26 amount_table["np_sum_qty"] = desc[1]["np_service_qty"] 27 amount_table["np_sum_fee"] = desc[1]["np_service_fee"] 28 amount_table["sum_np_fee"] = desc[1]["np_sum_fee"] 29 amount_table["sum_original_fee"] = desc[1]["np_sum_original_fee"] 30 end 31 -- un总费用统计 32 local un_sum_fee = "SELECT product_id, SUM(total_duration) AS un_sum_duration, " .. 33 " SUM(total_times) AS un_sum_cdrCnt, " .. 34 " SUM(total_fee) AS un_sum_fee " .. 35 " FROM dat_bill_" .. cycleid .. " WHERE call_type & 4097 > 0 AND product_id = '" .. record["product_id"] .. "';" 36 local rtn, desc = executeSql(un_sum_fee) 37 if rtn and next(desc) ~= nil then 38 amount_table["un_sum_duration"] = desc[1]["un_sum_duration"] 39 amount_table["un_total_times"] = desc[1]["un_sum_cdrCnt"] 40 amount_table["un_sum_fee"] = desc[1]["un_sum_fee"] 41 end 42 -- 构建sql语句 43 if value_count ~= 0 then 44 insert_sql = insert_sql .. "," 45 else 46 insert_sql = sql_const 47 end 48 insert_sql = insert_sql .. "('" .. 49 amount_table["product_id"] .. "', '" .. 50 amount_table["np_id"] .. "', " .. 51 amount_table["np_sum_duration"] .. ", " .. 52 amount_table["np_total_times"] .. ", " .. 53 amount_table["np_sum_qty"] .. ", " .. 54 amount_table["np_sum_fee"] .. ", " .. 55 amount_table["un_sum_duration"] .. ", " .. 56 amount_table["un_total_times"].. ", " .. 57 amount_table["un_sum_fee"] .. ", " .. 58 amount_table["sum_np_fee"] .. ", " .. 59 amount_table["sum_original_fee"] .. ")" 60 value_count = value_count + 1 61 if 3000 == value_count then 62 sum_count = sum_count + value_count 63 insert_sql = insert_sql .. "; commit;" 64 local rtn, result = executeSql(insert_sql) 65 if not rtn then 66 rtnstr["code"] = 561 67 rtnstr["msg"] = "Error. amount_sum_fee insert into sum_fee num : " .. sum_count .. " sql : " .. insert_sql 68 return false 69 else 70 local result = "compare: success to amount_sum_fee insert into sum_fee num : " .. sum_count 71 ngx.log(ngx.ERR, result) 72 end 73 insert_sql = "" 74 value_count = 0 75 end 76 end 77 if value_count > 0 then 78 sum_count = sum_count + value_count 79 insert_sql = insert_sql .. "; commit;" 80 local rtn, result = executeSql(insert_sql) 81 if not rtn then 82 rtnstr["code"] = 562 83 rtnstr["msg"] = "Error. amount_sum_fee insert into sum_fee num : " .. sum_count .. " sql : " .. insert_sql 84 return false 85 else 86 local result = "compare: success to amount_sum_fee insert into sum_fee num : " .. sum_count 87 ngx.log(ngx.ERR, result) 88 end 89 insert_sql = "" 90 value_count = 0 91 end 92 end 93 else 94 rtnstr["code"] = 560 95 rtnstr["msg"] = "Failed to select product_id amount_sum_fee error : " .. productid_set 96 return false 97 end 98 return true 99 end
使用的是SQL中的sum函数
【2】分析原因
数据库访问汇总数据时,SUM函数的结果可能为NULL值。如下图:
修改SQL语句,添加IFNULL判断,若为NULL,则为0即可。如下图:
如上原因分析。
【3】修复后代码
1 local function amount_sum_fee(cycleid) 2 local select_productid = "select product_id from np_cdr_" .. cycleid .. " group by product_id;" 3 local rtn, productid_set = executeSql(select_productid) 4 if rtn then 5 local value_count = 0 6 local sum_count = 0 7 local sql_const = "insert into compare_fee_" .. cycleid .. " (product_id, np_id, np_sum_duration, np_total_times, " .. 8 " np_sum_qty, np_sum_fee, un_sum_duration, un_total_times, un_sum_fee, sum_np_fee, sum_original_fee) values " 9 if type(productid_set) == 'table' and next(productid_set) ~= nil then 10 for key, record in pairs(productid_set) do 11 local amount_table = {} 12 amount_table["product_id"] = record["product_id"] 13 amount_table["np_id"] = 'all' 14 -- np总费用统计 15 local np_sum_fee = "SELECT product_id, IFNULL(SUM(duration), 0) AS np_sum_duration, " .. 16 " COUNT(id) AS np_sum_cdrCnt, " .. 17 " IFNULL(SUM(service_qty), 0) AS np_service_qty, " .. 18 " IFNULL(SUM(service_fee), 0) AS np_service_fee, " .. 19 " IFNULL(SUM(np_fee), 0) AS np_sum_fee, " .. 20 " IFNULL(SUM(original_fee), 0) AS np_sum_original_fee " .. 21 " FROM np_cdr_" .. cycleid .. " WHERE product_id = '" .. record["product_id"] .. "';" 22 local rtn, desc = executeSql(np_sum_fee) 23 if rtn and next(desc) ~= nil then 24 amount_table["np_sum_duration"] = desc[1]["np_sum_duration"] 25 amount_table["np_total_times"] = desc[1]["np_sum_cdrCnt"] 26 amount_table["np_sum_qty"] = desc[1]["np_service_qty"] 27 amount_table["np_sum_fee"] = desc[1]["np_service_fee"] 28 amount_table["sum_np_fee"] = desc[1]["np_sum_fee"] 29 amount_table["sum_original_fee"] = desc[1]["np_sum_original_fee"] 30 end 31 -- un总费用统计 32 local un_sum_fee = "SELECT product_id, IFNULL(SUM(total_duration), 0) AS un_sum_duration, " .. 33 " IFNULL(SUM(total_times), 0) AS un_sum_cdrCnt, " .. 34 " IFNULL(SUM(total_fee), 0) AS un_sum_fee " .. 35 " FROM dat_bill_" .. cycleid .. " WHERE call_type & 4097 > 0 AND product_id = '" .. record["product_id"] .. "';" 36 local rtn, desc = executeSql(un_sum_fee) 37 if rtn and next(desc) ~= nil then 38 amount_table["un_sum_duration"] = desc[1]["un_sum_duration"] 39 amount_table["un_total_times"] = desc[1]["un_sum_cdrCnt"] 40 amount_table["un_sum_fee"] = desc[1]["un_sum_fee"] 41 end 42 -- 构建sql语句 43 if value_count ~= 0 then 44 insert_sql = insert_sql .. "," 45 else 46 insert_sql = sql_const 47 end 48 insert_sql = insert_sql .. "('" .. 49 amount_table["product_id"] .. "', '" .. 50 amount_table["np_id"] .. "', " .. 51 amount_table["np_sum_duration"] .. ", " .. 52 amount_table["np_total_times"] .. ", " .. 53 amount_table["np_sum_qty"] .. ", " .. 54 amount_table["np_sum_fee"] .. ", " .. 55 amount_table["un_sum_duration"] .. ", " .. 56 amount_table["un_total_times"].. ", " .. 57 amount_table["un_sum_fee"] .. ", " .. 58 amount_table["sum_np_fee"] .. ", " .. 59 amount_table["sum_original_fee"] .. ")" 60 value_count = value_count + 1 61 if 3000 == value_count then 62 sum_count = sum_count + value_count 63 insert_sql = insert_sql .. "; commit;" 64 local rtn, result = executeSql(insert_sql) 65 if not rtn then 66 rtnstr["code"] = 561 67 rtnstr["msg"] = "Error. amount_sum_fee insert into sum_fee num : " .. sum_count .. " sql : " .. insert_sql 68 return false 69 else 70 local result = "compare: success to amount_sum_fee insert into sum_fee num : " .. sum_count 71 ngx.log(ngx.ERR, result) 72 end 73 insert_sql = "" 74 value_count = 0 75 end 76 end 77 if value_count > 0 then 78 sum_count = sum_count + value_count 79 insert_sql = insert_sql .. "; commit;" 80 local rtn, result = executeSql(insert_sql) 81 if not rtn then 82 rtnstr["code"] = 562 83 rtnstr["msg"] = "Error. amount_sum_fee insert into sum_fee num : " .. sum_count .. " sql : " .. insert_sql 84 return false 85 else 86 local result = "compare: success to amount_sum_fee insert into sum_fee num : " .. sum_count 87 ngx.log(ngx.ERR, result) 88 end 89 insert_sql = "" 90 value_count = 0 91 end 92 end 93 else 94 rtnstr["code"] = 560 95 rtnstr["msg"] = "Failed to select product_id amount_sum_fee error : " .. productid_set 96 return false 97 end 98 return true 99 end
【4】总结
Lua中使用SQL语句进行汇总数据时,切记需要作NULL判断。
Good Good Study, Day Day Up.
顺序 选择 循环 总结