如何借助gl_periods表,通过period_name查询gl_balances的指定期间数据?
解决gl_balances表按period_name范围查询的问题
直接用mmm-yy格式的字符串做范围比较会出错,比如Dec-22的字符串排序会在Jan-23之后,但实际时间上Dec-22早于Jan-23。利用gl_periods表的period_year(数值型年份)和period_num(数值型月份编号)可以准确实现期间范围筛选。
方法一:通过关联gl_periods表直接筛选
这种方式不需要额外变量,直接关联三张表来判断范围:
SELECT gb.* FROM gl_balances gb -- 关联当前数据对应的期间属性 JOIN gl_periods gp ON gb.period_name = gp.period_name -- 关联起始期间的属性 JOIN gl_periods gp_start ON gp_start.period_name = :period_name_from -- 关联结束期间的属性 JOIN gl_periods gp_end ON gp_end.period_name = :period_name_to WHERE -- 满足:年份大于起始年,或者同年且月份编号大于等于起始月 (gp.period_year > gp_start.period_year OR (gp.period_year = gp_start.period_year AND gp.period_num >= gp_start.period_num)) AND -- 满足:年份小于结束年,或者同年且月份编号小于等于结束月 (gp.period_year < gp_end.period_year OR (gp.period_year = gp_end.period_year AND gp.period_num <= gp_end.period_num));
方法二:先获取起止期间的年份和月份编号,再筛选
如果使用PL/SQL或支持变量的SQL环境,可以先查询出起止期间的数值属性,再做筛选,性能可能更优:
-- 第一步:获取起始期间的年份和月份编号 DECLARE v_start_year NUMBER; v_start_num NUMBER; v_end_year NUMBER; v_end_num NUMBER; BEGIN SELECT period_year, period_num INTO v_start_year, v_start_num FROM gl_periods WHERE period_name = :period_name_from; SELECT period_year, period_num INTO v_end_year, v_end_num FROM gl_periods WHERE period_name = :period_name_to; -- 第二步:查询目标数据 SELECT gb.* FROM gl_balances gb JOIN gl_periods gp ON gb.period_name = gp.period_name WHERE (gp.period_year > v_start_year OR (gp.period_year = v_start_year AND gp.period_num >= v_start_num)) AND (gp.period_year < v_end_year OR (gp.period_year = v_end_year AND gp.period_num <= v_end_num)); END; /
注意事项
- 确保
gl_periods表中的period_name与gl_balances表的period_name完全匹配(大小写、格式一致),否则关联会丢失数据。 - 如果
gl_periods中存在重复的period_name(如不同账套场景),需要添加额外过滤条件(比如账套ID)确保取到正确的期间属性。
内容的提问来源于stack exchange,提问作者James Wilson
相关产品推荐
相关产品推荐

