You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 19:35:21