SQL查询:指定日期无数据时取批次最新日期并返回对应余额字段
批量查询账户余额SQL实现方案
原有写法问题说明
你之前尝试的SQL存在两个核心问题:
- 没有对指定批次做全局的日期优先级判断,仅单独查询最大日期未和余额查询逻辑结合
- 未对saldo_do和saldo_br做非空合并处理,会同时返回两个字段
核心查询逻辑
你可以通过窗口函数排序+字段合并的方式直接实现需求,核心SQL语句如下:
-- 替换以下两个参数为你实际的输入值:目标批次@target_batch、目标查询日期@target_date SELECT COALESCE(saldo_do, saldo_br) AS account_balance, dat_extr AS actual_query_date FROM ( SELECT saldo_do, saldo_br, dat_extr, -- 排序规则:目标日期匹配的排第一,其余按日期倒序取最新 ROW_NUMBER() OVER ( ORDER BY CASE WHEN dat_extr = @target_date THEN 1 ELSE 2 END, dat_extr DESC ) AS rn FROM trr_extracts WHERE batch = @target_batch ) t WHERE rn = 1;
逻辑说明
- 内层查询筛选指定批次的所有数据,通过
ROW_NUMBER()做优先级排序:优先匹配输入的目标日期,若不存在则自动取该批次最新的日期数据,取排序第一的行即为符合要求的数据 - 外层用
COALESCE(saldo_do, saldo_br)合并两个余额字段,自动返回唯一的非空余额值,无需额外判断空值
存储过程(Procedure)完整示例(MySQL语法)
DELIMITER // CREATE PROCEDURE GetBatchAccountBalance( IN p_batch INT, IN p_target_date DATE, OUT p_account_balance DECIMAL(18,2), OUT p_actual_date DATE ) BEGIN SELECT COALESCE(saldo_do, saldo_br), dat_extr INTO p_account_balance, p_actual_date FROM ( SELECT saldo_do, saldo_br, dat_extr, ROW_NUMBER() OVER ( ORDER BY CASE WHEN dat_extr = p_target_date THEN 1 ELSE 2 END, dat_extr DESC ) AS rn FROM trr_extracts WHERE batch = p_batch ) t WHERE rn = 1; END // DELIMITER ; -- 调用示例 CALL GetBatchAccountBalance(135, '2019-03-21', @balance, @actual_date); SELECT @balance, @actual_date;
适配说明
- 若使用Oracle语法,仅需调整存储过程的定义语法,核心排序、
COALESCE逻辑无需改动 - 若dat_extr字段为字符串存储的日期,需先统一转换为日期格式再做匹配,避免格式不匹配导致的判断错误
内容的提问来源于stack exchange,提问作者CherrJ
相关产品推荐
相关产品推荐

