目标是迭代表中的所有行,并根据ext_cost的总和更新每行的summary_total,其中ticket值等于当前行的票证值。可能是一个简单的语法问题或与我的MySQL版本不兼容 - 检查......有什么想法吗?
DROP PROCEDURE IF EXISTS TOTALCALC;
DELIMITER $
CREATE PROCEDURE TOTALCALC( IN _OFFSET INTEGER ) -- procedure with offset parameter to use like Oracle's rownum...
BEGIN
DECLARE n INT DEFAULT 0; -- declare total row count variable
DECLARE i INT DEFAULT 0; -- set count up variable
SELECT COUNT(*) FROM table INTO n; -- set total row count variable
SET i=0; -- initial count up number, may be redundant
WHILE i<n DO -- do while counting up to total row count:
PREPARE STMT FROM 'SELECT TICKET:=@t FROM table LIMIT ?,1'; -- set ticket variable from current row using prepared statement to allow offset variable in place of rownum (workaround)
SET i = i + 1; -- count up toward total row count
SET @OFFSET = _OFFSET;
EXECUTE STMT USING @OFFSET;
SET @OFFSET = @OFFSET + 1; -- next row
UPDATE table SET table.SUMMARY_TOTAL = (select * from (select sum(EXT_COST) from table where TICKET = @t) AS X) WHERE TICKET = @t; -- nested subquery workaround to update using/including data selected from same table
DEALLOCATE PREPARE STMT;
END WHILE;
END $
DELIMITER ;
CALL TOTALCALC(0); -- run starting at offset 0, which is row 1
答案 0 :(得分:0)
为什么你不能使用join
:
update t join
(select ticket, sum(ext_cost) as sum_ext_cost
from t
group by ticket
) tt
on t.ticket = tt.ticket
set t.summary_total = tt.sum_ext_cost;
这实际上看起来很尴尬,而且是一个坏主意。你有一个tickets
表,每张票有一行吗?如果是这样,摘要应该放在该表中,您只需使用join
获取它。
答案 1 :(得分:0)
抛开关于表格设计的讨论,以及为什么一组行的summary_cost
存储在每一行中......
处理RBAR(通过痛苦的行排)是一种SQL反模式。
对于&#34; set&#34;我们通常会更好地使用SQL思维。数据的。我们不是处理单个行,而是处理一组行。
程序的整个过程看起来根本就是错误的。除了重复使用SELECT ... LIMIT n,1
而没有ORDER BY
子句之类的问题之外,每次运行时依赖MySQL以相同的顺序返回行,并且在过程运行时依赖于没有插入或删除行。
很难弄清楚该程序究竟应该做什么。这很难破译,我怜悯不得不坚持下去的那个不幸的灵魂。
如果该过程的目标是为表中的行组计算summary_cost
,并将计算出的summary_cost
分配给该组中每行的列...
使用单个SQL语句可以更清楚地完成这一点。
首先,我们写一个SELECT
语句,如下所示:
SELECT t.id
, t.ticket
, t.summary_cost AS old_summary_cost
, s.summary_cost AS new_summary_cost
FROM table t
JOIN ( SELECT r.*
FROM ( SELECT q.ticket
, SUM(q.ext_cost) AS summary_total
FROM table q
GROUP BY q.ticket
) r
) s
ON s.ticket = t.ticket
这样做的目的是返回我们想要更新的行,以及我们想要分配给summary_cost
的新值。
如果有些行不应该更新,或者我们只想更新特定的行,我们可以在WHERE
子句中添加适当的谓词。我们修改该查询,直到它返回我们想要更新的行,以及我们要分配的新值。
一旦我们得到SELECT
语句,并且我们对结果感到满意,那么我们才会将其转换为UPDATE
语句。
(您可以指出MySQL中有关从同一语句中正在更新的表中进行选择的限制,以及使用其他内联视图包装器的解决方法。我们在编写{时考虑到这一限制{1}}陈述。)
我们只需将SELECT
替换为SELECT ... FROM
关键字,然后添加UPDATE
子句(如果有SET
子句,则添加WHERE
子句。)
我们最终得到:
UPDATE table t
JOIN ( SELECT r.*
FROM ( SELECT q.ticket
, SUM(q.ext_cost) AS summary_total
FROM table q
GROUP BY q.ticket
) r
) s
SET t.summary_total = s.summary_total
ON t.ticket = s.ticket