PostgreSQL中排除周末计算工作日到期幻灯片数量的问题
解决方案:按工作日统计到期幻灯片数量
你的查询核心问题是用自然日计算到期间隔,未排除周末。要实现按N个工作日后到期统计,需要先计算当前日期之后的第N个工作日,再匹配对应到期日的幻灯片数量,同时过滤掉周末的到期记录。
方案1:直接在查询中计算目标工作日
不需要创建函数,直接通过子查询生成并筛选工作日日期:
SELECT -- 统计1个工作日后到期的幻灯片 SUM(CASE WHEN orders.duedate::date = ( SELECT d FROM generate_series(current_date + 1, current_date + 10) d WHERE extract(isodow from d) BETWEEN 1 AND 5 -- 仅保留周一到周五 ORDER BY d LIMIT 1 ) THEN nullif(orders.slides, 0) ELSE 0 END) AS "Slides (1 Work Day)", -- 统计2个工作日后到期的幻灯片 SUM(CASE WHEN orders.duedate::date = ( SELECT d FROM generate_series(current_date + 1, current_date + 10) d WHERE extract(isodow from d) BETWEEN 1 AND 5 ORDER BY d LIMIT 1 OFFSET 1 -- 取第2个工作日 ) THEN nullif(orders.slides, 0) ELSE 0 END) AS "Slides (2 Work Days)", -- 如需统计更多工作日,调整OFFSET值(N个工作日则OFFSET N-1) SUM(CASE WHEN orders.duedate::date = ( SELECT d FROM generate_series(current_date + 1, current_date + 10) d WHERE extract(isodow from d) BETWEEN 1 AND 5 ORDER BY d LIMIT 1 OFFSET 2 ) THEN nullif(orders.slides, 0) ELSE 0 END) AS "Slides (3 Work Days)" FROM orders WHERE extract(isodow from orders.duedate::date) BETWEEN 1 AND 5 -- 排除周末的到期记录 AND orders.duedate::date > current_date; -- 仅统计未来到期的记录
方案2:自定义函数简化代码
如果需要统计多个工作日间隔,创建一个计算“N个工作日后日期”的函数会更简洁:
-- 创建自定义函数:计算指定日期后N个工作日的日期 CREATE OR REPLACE FUNCTION add_work_days(start_date DATE, days INT) RETURNS DATE AS $$ BEGIN RETURN ( SELECT start_date + generate_series(1, days*2) WHERE extract(isodow from start_date + generate_series(1, days*2)) BETWEEN 1 AND 5 ORDER BY 1 LIMIT 1 OFFSET days-1 ); END; $$ LANGUAGE plpgsql;
之后直接调用函数编写统计查询:
SELECT SUM(CASE WHEN orders.duedate::date = add_work_days(current_date, 1) THEN nullif(orders.slides, 0) ELSE 0 END) AS "Slides (1 Work Day)", SUM(CASE WHEN orders.duedate::date = add_work_days(current_date, 2) THEN nullif(orders.slides, 0) ELSE 0 END) AS "Slides (2 Work Days)" FROM orders WHERE extract(isodow from orders.duedate::date) BETWEEN 1 AND 5 AND orders.duedate::date > current_date;
关键说明
extract(isodow from date):PostgreSQL中返回1(周一)到7(周日),用BETWEEN 1 AND 5过滤工作日。generate_series(current_date + 1, current_date + 10):生成未来10天的日期(足够覆盖最多5个工作日的间隔),再筛选出工作日。nullif(orders.slides, 0):确保幻灯片数量为0时不被计入总和,保留你原逻辑的统计规则。
内容的提问来源于stack exchange,提问作者Kris
相关产品推荐
相关产品推荐

