如何用FOR循环将tbl_ledger每日余额总和插入tbl_ledger_input
解决方案
首先说明:SQL是集合型语言,优先推荐用聚合查询直接插入,比FOR循环效率高得多:
最优方案:无循环直接插入
INSERT INTO tbl_ledger_input (balance, eff_date) SELECT CONCAT(SUM(CAST(REPLACE(balance, '$', '') AS DECIMAL(10,2))), '$'), UPPER(eff_date) -- 统一日期格式,避免因大小写导致的重复分组 FROM tbl_ledger GROUP BY UPPER(eff_date);
逻辑说明
- 用
REPLACE(balance, '$', '')去掉余额中的$符号,转成数值型DECIMAL(10,2) - 按统一大小写后的
eff_date分组,计算每组的余额总和 - 把总和拼接回$符号,插入目标表
如果你坚持要用FOR循环实现(仅小数据量场景建议,大数据量性能较差),以下是不同数据库的实现方式:
MySQL 实现(存储过程+游标循环)
DELIMITER // CREATE PROCEDURE InsertLedgerSummary() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE v_eff_date VARCHAR(20); DECLARE v_total DECIMAL(10,2); -- 定义游标获取所有唯一日期 DECLARE date_cursor CURSOR FOR SELECT DISTINCT UPPER(eff_date) FROM tbl_ledger; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN date_cursor; read_loop: LOOP FETCH date_cursor INTO v_eff_date; IF done THEN LEAVE read_loop; END IF; -- 计算当前日期的总余额 SELECT SUM(CAST(REPLACE(balance, '$', '') AS DECIMAL(10,2))) INTO v_total FROM tbl_ledger WHERE UPPER(eff_date) = v_eff_date; -- 插入目标表 INSERT INTO tbl_ledger_input (balance, eff_date) VALUES (CONCAT(v_total, '$'), v_eff_date); END LOOP; CLOSE date_cursor; END // DELIMITER ; -- 执行存储过程 CALL InsertLedgerSummary();
SQL Server 实现(游标循环)
DECLARE @eff_date VARCHAR(20), @total_balance DECIMAL(10,2) -- 声明游标获取唯一日期 DECLARE date_cursor CURSOR FOR SELECT DISTINCT UPPER(eff_date) FROM tbl_ledger OPEN date_cursor FETCH NEXT FROM date_cursor INTO @eff_date WHILE @@FETCH_STATUS = 0 BEGIN -- 计算当前日期总余额 SELECT @total_balance = SUM(CAST(REPLACE(balance, '$', '') AS DECIMAL(10,2))) FROM tbl_ledger WHERE UPPER(eff_date) = @eff_date -- 插入数据 INSERT INTO tbl_ledger_input (balance, eff_date) VALUES (CONCAT(@total_balance, '$'), @eff_date) FETCH NEXT FROM date_cursor INTO @eff_date END CLOSE date_cursor DEALLOCATE date_cursor
注意事项
- 处理
balance字段时必须先去除$符号再做数值计算,否则会报错 - 统一
eff_date的大小写,避免因5feb和5FEB被识别为不同日期 - 游标循环仅适合小数据量场景,数据量大时优先用聚合插入方案
内容的提问来源于stack exchange,提问作者sami
相关产品推荐
相关产品推荐

