我有这两个函数和一个触发器来处理我正在处理的项目的点计算,与此交互以开始调用所有内容的示例查询是SELECT insertRun(76561198117520501, 99, 0, 757.91015625, 0, TRUE) as run_id
。在getRunPointValue
函数的某个地方,它导致了除以0的错误,并且在除以0的仅有的两个位置,如果它是0,则我显式地将正在使用的值设置为1,因此正在被divided不应该是0。这个问题已经在我的insertRun
函数中被注解掉了UPDATE
,但是这个函数调用是必要的,否则新的运行就不会被排名。这个函数99%的时间都能工作,而且它在一些奇怪的边缘情况下,比如你要么排名第一,要么排名最后,它会导致除以0的错误,从我所能观察到的。
我收到的确切错误代码是
1365,被零除
下面是我正在使用的SQL函数和触发器。
CREATE FUNCTION insertRun(userid BIGINT UNSIGNED, mid INT, styleid INT, run_time FLOAT(12,4), type INT, best BOOLEAN)
RETURNS INT
BEGIN
DECLARE runid INT;
DECLARE totalPoints INT DEFAULT 0;
IF best = TRUE THEN
UPDATE surf_run SET best_run = FALSE WHERE user_id = userid AND map_id = mid AND style = styleid AND run_type = type;
END IF;
INSERT INTO surf_run (user_id, map_id, style, time, run_type, best_run) VALUES (userid, mid, styleid, run_time, type, best);
-- if best_run is true then set all other runs by user_id and map_id to false
SELECT run_id INTO runid FROM surf_run WHERE user_id = userid AND map_id = mid AND style = styleid AND run_type = type AND best_run = TRUE ORDER BY run_id DESC LIMIT 1;
--UPDATE surf_run SET points = getRunPointValue(runid) WHERE run_id = runid;
SELECT SUM(points) INTO totalPoints FROM surf_run WHERE user_id = userid AND best_run=TRUE;
UPDATE surf_user SET points = totalPoints WHERE user_id = userid;
RETURN runid;
END;
CREATE FUNCTION getRunPointValue(id INT)
RETURNS INT
exit_getrunpointvalue:BEGIN
DECLARE points INT DEFAULT 10;
DECLARE total_completions INT DEFAULT 1;
DECLARE place INT DEFAULT 1;
DECLARE run_time FLOAT(12,4);
DECLARE run_style INT;
DECLARE type INT;
DECLARE mapid INT;
DECLARE maptier INT;
DECLARE tierMulti FLOAT(3,2) DEFAULT 1.0;
DECLARE percentile FLOAT(12,4);
DECLARE total_points INT DEFAULT 3000;
DECLARE percentile_potential INT;
DECLARE completionsbonus INT DEFAULT 0;
DECLARE temp FLOAT;
DECLARE bracket_min INT DEFAULT 0;
DECLARE bracket_max INT DEFAULT 0;
SELECT time INTO run_time FROM surf_run WHERE run_id = id LIMIT 1;
SELECT style INTO run_style FROM surf_run WHERE run_id = id;
SELECT run_type INTO type FROM surf_run WHERE run_id = id;
SELECT map_id INTO mapid FROM surf_run WHERE run_id = id;
SELECT tier INTO maptier FROM surf_map WHERE map_id = mapid;
IF type < 0 THEN
LEAVE exit_getrunpointvalue;
END IF;
SELECT COUNT(*) INTO place FROM surf_run WHERE map_id = mapid AND time <= run_time AND style = run_style AND run_type = type AND best_run = TRUE;
SELECT COUNT(*) INTO total_completions FROM surf_run WHERE map_id = mapid AND style = run_style AND run_type = type AND best_run = TRUE;
IF total_completions <= 0 THEN
SET total_completions = 1;
END IF;
SET completionsbonus = FLOOR((total_completions / 2) * 0.6);
IF maptier = 1 THEN
SET tierMulti = 1.0;
ELSEIF maptier = 2 THEN
SET tierMulti = 1.53;
ELSEIF maptier = 3 THEN
SET tierMulti = 2.5;
ELSEIF maptier = 4 THEN
SET tierMulti = 3.8;
ELSEIF maptier = 5 THEN
SET tierMulti = 6.0;
ELSEIF maptier = 6 THEN
SET tierMulti = 8.5;
END IF;
IF place = 0 THEN
SET place = 1;
END IF;
IF place = 1 THEN
SET points = 1500 + completionsbonus;
ELSEIF place = 2 THEN
SET points = 1250 + completionsbonus;
ELSEIF place = 3 THEN
SET points = 1100 + completionsbonus;
ELSEIF place = 4 THEN
SET points = 1000 + completionsbonus;
ELSEIF place = 5 THEN
SET points = 900 + completionsbonus;
ELSE
SET percentile = (place / total_completions);
IF percentile <= 0.05 THEN
SET percentile_potential = 800;
SET points = 600;
SET bracket_min = 0;
SET bracket_max = total_completions * 0.05;
ELSEIF percentile <= 0.10 THEN
SET bracket_max = total_completions * 0.05 + 1;
SET bracket_max = total_completions * 0.1;
SET percentile_potential = 600;
SET points = 450;
ELSEIF percentile <= 0.15 THEN
SET bracket_max = total_completions * 0.1 + 1;
SET bracket_max = total_completions * 0.15;
SET percentile_potential = 450;
SET points = 200;
ELSEIF percentile <= 0.25 THEN
SET bracket_max = total_completions * 0.15 + 1;
SET bracket_max = total_completions * 0.25;
SET percentile_potential = 200;
SET points = 10;
END IF;
SET points = points + GREATEST(0, ROUND(percentile_potential - percentile_potential * LOG(place, bracket_max))) + completionsbonus;
END IF;
RETURN FLOOR(points * tierMulti);
END;
CREATE TRIGGER updateRunPointValue AFTER INSERT ON surf_run FOR EACH ROW
exit_updaterunpoints_trugger:BEGIN
DECLARE place INT DEFAULT 0;
DECLARE total INT DEFAULT 1;
DECLARE runoffset INT DEFAULT 0;
DECLARE worst_time FLOAT(12,4);
IF NEW.run_type < 0 THEN
LEAVE exit_updaterunpoints_trugger;
END IF;
SELECT COUNT(*) INTO place FROM surf_run WHERE map_id = NEW.map_id AND time <= NEW.time AND style = NEW.style AND run_type = NEW.run_type AND best_run = TRUE;
SELECT COUNT(*) INTO total FROM surf_run WHERE map_id = NEW.map_id AND style = NEW.style AND run_type = NEW.run_type AND best_run = TRUE;
-- if total < 250 then
-- LEAVE exit_updaterunpoints_trugger;
-- END IF;
SET runoffset = (total * 0.25) + 1;
SELECT time INTO worst_time FROM surf_run WHERE map_id = NEW.map_id AND style = NEW.style AND run_type = NEW.run_type AND best_run = TRUE ORDER BY time DESC LIMIT 1 OFFSET runoffset;
call rerunPointValue(NEW.map_id, worst_time, NEW.style, NEW.run_type);
END;```
1条答案
按热度按时间xvw2m8pv1#
我不确定这是怎么发生的,但我怀疑
total_completions
被设置为NULL
而不是0
。