【问题标题】:How to add a given number of days to a date and exclude weekends如何将给定的天数添加到日期并排除周末
【发布时间】:2021-07-19 21:15:01
【问题描述】:

如何在日期字段中添加天数并跳过周末的计算。

ex: if  Date  = 7/7/2021  then  Due Date = 07/21/2021`

Date = uxsubmtlDateRcvdDOP,
Number of days = 10, 
Due Date = uxsubmtlDateRcvdDOP + 10`

我有

Select uxsubmtlDateRcvdDOP + 10 as duedate

但这也计算周末。

【问题讨论】:

  • @matthias 这个问题充满了关于 SQL Server (T-SQL) 的答案,尽管它没有这样的标签。但我对 Oracle 的看法也一样,因为几周前有人问过这个问题
  • @Matthias 这个问题也在错误的方向进行计算,因为它需要两个日期作为输入并计算它们之间的工作日数作为输出; OP 希望将一个日期和多个工作日作为输入并计算一个日期作为输出。
  • 您的工作日是周一到周五吗? (在许多国家,情况并非如此——您应该始终准确地说明“工作周”的含义。)另外,如果输入日期是周六或周日怎么办?我假设在这种情况下,增加 1 个工作日意味着下周一返回,但请确认任一方式。

标签: sql oracle


【解决方案1】:

这可以在 Oracle 中通过一个小的 PL/SQL 函数来完成,该函数使用 TRUNC(<date>, 'IW') 来查找包含您的日期的一周中的星期一。

create or replace function plus_weekdays(d0 date, weekdays number) return date
is
  d0_Monday            date;    /* Monday <= d0 */
  weekdays_from_Monday number;  /* # of weekdays to increment from d0_Monday */
  nweeks               int;     /* # of weeks to increment from d0_Monday */
  ndays                number;  /* # of days to increment after nweeks */
begin
  d0_Monday := trunc(d0, 'iw');

  if d0 - d0_Monday >= 5 then
    -- This case means the given date is a Saturday or Sunday.
    -- We round the given date up to the next Monday and decerement the 
    -- number of weekdays that we are adding. For example:
    --   Saturday - 1 = Thursday (computed as Monday - 2)
    --   Saturday + 0 = Friday   (computed as Monday - 1)
    --   Saturday + 1 = Monday   (computed as Monday + 0)
    --   Saturday + 2 = Tuesday  (computed as Monday + 1)

    d0_Monday := d0_Monday + 7;
    weekdays_from_Monday := weekdays - 1;
  else
    weekdays_from_Monday := weekdays + (d0 - d0_Monday);
  end if;

  nweeks := floor(weekdays_from_Monday / 5);
  ndays  := (weekdays_from_Monday - nweeks * 5);

  return d0_Monday + nweeks * 7 + ndays;
end;
/
show errors;

SQL> select plus_weekdays(DATE '2020-07-07', 10) from dual;

PLUS_WEEK                                                                       
---------                                                                       
21-JUL-20                                                                       

【讨论】:

  • 请注意remainder是Oracle关键字,所以最好不要在代码中使用它作为变量名。此外,如果输入日期是星期六/星期日,则 OP 应该澄清所需的行为(大概添加 1 个工作日应该是下一个星期一,在这种情况下,您需要对代码进行一些小的修改来解决这个问题)。不过,除此之外,这可能是最简单的方法。 +1
  • 公平积分。我已经根据您的 cmets 更新了 PL/SQL 代码。感谢您的观看。
【解决方案2】:

你可以使用:

SELECT date_value,
       added_weekdays,
       weekday_date_value
       + MOD(added_weekdays, 5)        -- Number of days of part week
       + FLOOR(added_weekdays / 5) * 7 -- Number of full weeks
       + CASE TRUNC( weekday_date_value + MOD(added_weekdays, 5) )
              - TRUNC( weekday_date_value + MOD(added_weekdays, 5), 'IW' )
         WHEN 5 THEN 2
         WHEN 6 THEN 1
         ELSE 0 END                    -- Shift value if it falls on a weekend.
         AS final_value
FROM   (
  SELECT t.*,
         date_value
         + CASE TRUNC(date_value) - TRUNC(date_value, 'IW')
           WHEN 5 THEN 2
           WHEN 6 THEN 1
           ELSE 0 END AS weekday_date_value -- Shift the start date if it is on
                                            -- a weekend. 
  FROM   table_name t
)

其中,对于样本数据:

CREATE TABLE table_name ( date_value, added_weekdays ) AS
SELECT DATE '2021-07-07', 10 FROM DUAL UNION ALL
SELECT DATE '2021-07-07', 11 FROM DUAL UNION ALL
SELECT DATE '2021-07-07', 12 FROM DUAL UNION ALL
SELECT DATE '2021-07-07', 13 FROM DUAL UNION ALL
SELECT DATE '2021-07-10',  0 FROM DUAL UNION ALL
SELECT DATE '2021-07-10',  1 FROM DUAL;

输出(日期格式为YYYY-MM-DD (DY)):

DATE_VALUE ADDED_WEEKDAYS FINAL_VALUE
2021-07-07 (WED) 10 2021-07-21 (WED)
2021-07-07 (WED) 11 2021-07-22 (THU)
2021-07-07 (WED) 12 2021-07-23 (FRI)
2021-07-07 (WED) 13 2021-07-26 (MON)
2021-07-10 (SAT) 0 2021-07-12 (MON)
2021-07-10 (SAT) 1 2021-07-13 (TUE)

db小提琴here

【讨论】:

    【解决方案3】:
    Dateadd(mydate,,trunc(mydays/5)*7 + mod(mydays,5) + 2*trunc((weekday(mydate)+mod(mydays,5))/7))
    

    最后一个学期检查你是否跨越了最后一个周末的界限。

    如果您的开始日期是周六或周日,这有点奇怪。周五 + 1 天 = 周一,周六 + 1 天 = 周二,但周日 + 1 天是周一。

    【讨论】:

    • 感谢您的回答,但 Dateadd 在 Oracle Sql 开发人员中不起作用,这让我很失望。
    猜你喜欢
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多