如何调整SQL查询以统计参数日期所在月份的薪酬期间数量
问题说明
现有pay_time_periods表数据如下:
PAYROLL_ID START_DATE END_DATE PERIOD_NUM 10 01-MAY-2023 10-MAY-2023 1 10 11-MAY-2023 18-MAY-2023 2 10 19-MAY-2023 25-MAY-2023 3 10 26-MAY-2023 05-JUN-2023 4
需求是统计传入参数:p_process_date所在月份的薪酬期间总数(比如参数为5月任意日期时,预期返回4)。原SQL存在逻辑偏差,以下是修正方案:
修正后的SQL
SELECT COUNT(DISTINCT PERIOD_NUM) AS period_count FROM pay_time_periods WHERE PAYROLL_ID = 10 -- 若需统计所有薪酬组可移除该条件 AND ( -- 期间起始于目标月份 TRUNC(START_DATE, 'MM') = TRUNC(:p_process_date, 'MM') -- 期间结束于目标月份 OR TRUNC(END_DATE, 'MM') = TRUNC(:p_process_date, 'MM') -- 期间跨目标月份(覆盖整个月) OR (TRUNC(START_DATE, 'MM') < TRUNC(:p_process_date, 'MM') AND TRUNC(END_DATE, 'MM') > TRUNC(:p_process_date, 'MM')) )
关键修改点
- 修正筛选逻辑:原SQL仅筛选包含
:p_process_date的期间,无法覆盖跨月的期间(比如示例中第4条记录)。调整后的条件覆盖了所有与参数所在月份有重叠的期间类型,确保统计结果符合预期。 - 移除无效关联:原SQL引用了未声明的
ptp表,且papf.person_number无关联逻辑,直接基于单表查询即可满足需求。如果需要按人员分组统计,可补充关联逻辑,调整后的版本如下:
SELECT ptp.PAYROLL_ID, papf.person_number, COUNT(DISTINCT ptp.PERIOD_NUM) AS period_count FROM pay_time_periods ptp JOIN per_all_people_f papf ON ptp.person_id = papf.person_id -- 替换为实际关联字段 AND :p_process_date BETWEEN papf.effective_start_date AND papf.effective_end_date WHERE ( TRUNC(ptp.START_DATE, 'MM') = TRUNC(:p_process_date, 'MM') OR TRUNC(ptp.END_DATE, 'MM') = TRUNC(:p_process_date, 'MM') OR (TRUNC(ptp.START_DATE, 'MM') < TRUNC(:p_process_date, 'MM') AND TRUNC(ptp.END_DATE, 'MM') > TRUNC(:p_process_date, 'MM')) ) GROUP BY ptp.PAYROLL_ID, papf.person_number
- 简化聚合方式:用
COUNT(DISTINCT)直接统计唯一期间数,比原SQL的窗口函数加DISTINCT的写法更简洁高效。
内容的提问来源于stack exchange,提问作者SSA_Tech124
相关产品推荐
相关产品推荐

