【问题标题】:Calculating pay dates计算支付日期
【发布时间】:2022-11-26 05:25:45
【问题描述】:

我们使用双月工资单,员工在每月的第 15 天和最后几天收到工资。

如果这些日子是周六、周日或节假日,那么我们会在之前的最后一天收到工资,那一天不是周六、周日或节假日。

例如,以本周为例,4 月 15 日是星期五,但它被定义为假期,因此应在 4 月 14 日星期四向人们付款。

我设法得到一个部分查询,我可以在其中排除周末和节假日,但我可以使用一些帮助来确定应该在什么日期向人们付款。我的输出应该只包括发薪日。我想为当年的 1 月到 12 月生产年产量。

我在想,一旦假期和周末被排除在外,这个月的最后一个发薪日可能是 last_day() 吗?


CREATE OR REPLACE FUNCTION gen_dates(i_from_date IN DATE, i_end_date IN DATE, i_min_delta IN NUMBER, i_max_delta IN NUMBER, i_num_rows IN NUMBER) 
RETURN VARCHAR2 
SQL_MACRO 
IS 
BEGIN 
RETURN q'{
SELECT start_date, end_date
   FROM ( 
        SELECT pivot_date AS start_date, pivot_date + NUMTODSINTERVAL( i_min_delta + (i_max_delta-i_min_delta) * DBMS_RANDOM.VALUE(), 'hour') AS end_date 
        FROM (
            SELECT pivot_date + DBMS_RANDOM.VALUE() AS pivot_date            
            FROM ( 
                SELECT rownum AS rn, pivot_date AS pivot_date FROM ( 
                    SELECT TRUNC(i_from_date)+level-1 AS pivot_date FROM DUAL 
                    CONNECT BY TRUNC(i_from_date)+level-1<=TRUNC(i_end_date) 
                ) 
            ) 
            CONNECT BY LEVEL <= i_num_rows AND PRIOR rn = rn AND PRIOR sys_guid() IS NOT NULL 
        )
    ) 
}' ; 
END;
/

create table holidays(
          holiday_date DATE not null,
          holiday_name VARCHAR2(20),
          constraint holidays_pk primary key (holiday_date),
          constraint is_midnight check ( holiday_date = trunc ( holiday_date ) )
        );

INSERT into holidays (HOLIDAY_DATE,HOLIDAY_NAME)
        WITH dts as (
          select to_date('15-APR-2022 00:00:00','DD-MON-YYYY HH24:MI:SS'), 'Passover 2022' from dual union all
          select to_date('31-DEC-2022 00:00:00','DD-MON-YYYY HH24:MI:SS'), 'New Year Eve 2022' from dual
        )
        SELECT * from dts;

SELECT
        c.dt,
       to_char(c.dt, 'DY') as dow
FROM generate_dates(
TIMESTAMP '2022-01-01 00:00:00',
TIMESTAMP '2022-04-30 00:00:00',
 1, 'DAY') c
where 
to_char(c.dt, 'DY') NOT IN ('SAT', 'SUN') 
AND NOT EXISTS (
             SELECT 1
             FROM   holidays h
             WHERE  c.dt = h.holiday_date
           );

【问题讨论】:

    标签: sql oracle date


    【解决方案1】:

    我认为我要遵循的基本思想是获取所有没有周末和节假日的日期,然后找到每个月的最大天数和每个月的最大天数 <= 15 号。

    获取所有没有周末和节假日的日期:

    WITH noholidays AS
    (
    SELECT dt
    FROM 
     generate_dates(
      TIMESTAMP '2022-01-01 00:00:00',
      TIMESTAMP '2022-04-30 00:00:00',
      1, 'DAY') c
    WHERE to_char(dt, 'DY') NOT IN ('SAT', 'SUN')
     AND dt NOT IN (SELECT holiday_date FROM holidays)
    )
    

    然后,从那里获取每个月的最大日期unioned,最大日期为 <= 每个月的 15 日。

     SELECT max(dt) payday
     FROM noholidays
     GROUP BY to_char(dt, 'YYYY-MM')
    UNION ALL
     SELECT max(dt)
     FROM noholidays
     WHERE to_number(to_char(dt, 'DD')) <= 15
     GROUP BY to_char(dt, 'YYYY-MM')
    ORDER BY payday
    

    有一个 working example in this fiddle,尽管我使用 CTE 生成当年的所有日期 (borrowed from here),因为我无权访问您的 generate_dates UDF(但您可以只使用 generate_dates)。

    WITH alldatesinyear AS (
    SELECT
        ST_DT + LEVEL - 1 dt
    FROM
        (
            SELECT
                TRUNC(SYSDATE, 'YEAR') ST_DT,
                TRUNC(SYSDATE, 'YEAR') + INTERVAL '12' MONTH - INTERVAL '1' DAY END_DT
            FROM DUAL
        )
    CONNECT BY LEVEL <= END_DT - ST_DT),
    noholidays AS (
     SELECT dt
     FROM alldatesinyear
     WHERE to_char(dt, 'DY') NOT IN ('SAT', 'SUN')
      AND dt NOT IN (SELECT holiday_date FROM holidays)
    )
    SELECT max(dt) payday
    FROM noholidays
    GROUP BY to_char(dt, 'YYYY-MM')
    UNION ALL
    SELECT max(dt)
    FROM noholidays
    WHERE to_number(to_char(dt, 'DD')) <= 15
    GROUP BY to_char(dt, 'YYYY-MM')
    ORDER BY payday
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-13
      • 1970-01-01
      • 1970-01-01
      • 2016-10-17
      相关资源
      最近更新 更多