Есть ли простой способ определить следующий рабочий день из даты, когда выходные и праздничные дни включены в расчет? - PullRequest
0 голосов
/ 28 июня 2019

У меня есть таблица будущего, которая показывает праздничные и выходные дни вместе с календарными датами, и я хочу добавить поле следующего рабочего дня, основанное на выходных и выходных.

Например: 2 января 2020 года - выходной день, 1 января - тоже. 1 января 2020 года - среда, поэтому следующий рабочий день должен быть 3 января. (пропускает 2-е, пятница - рабочий день).

Есть ли простая функция или цикл, который может сделать это просто? Мне нужно сделать это только один раз, поэтому я не слишком беспокоюсь о том, чтобы не использовать операцию set.

Я создал то, что, как я предполагал, было заявлением о наихудшем случае в мире, но я понял, что решение было просто неуклюжим и не поддерживалось.

enter image description here

Ответы [ 4 ]

0 голосов
/ 29 июня 2019

Попробуйте что-то вроде этого:

create table dbo.HolidayList(Holiday date)
insert into HolidayList(Holiday)values
('2019-07-01T00:00:00.000'),('2019-07-09T00:00:00.000'),('2019-08-01T00:00:00.000'),
('2019-08-02T00:00:00.000'),('2019-08-05T00:00:00.000'),('2019-09-02T00:00:00.000'),
('2019-10-14T00:00:00.000'),('2019-11-11T00:00:00.000'),('2019-12-25T00:00:00.000'),
('2019-12-26T00:00:00.000'),('2020-01-01T00:00:00.000'),('2020-02-10T00:00:00.000'),
('2020-02-17T00:00:00.000'),('2020-03-17T00:00:00.000'),('2020-04-10T00:00:00.000'),
('2020-04-13T00:00:00.000'),('2020-04-23T00:00:00.000'),('2020-05-18T00:00:00.000'),
('2020-05-25T00:00:00.000'),('2020-06-24T00:00:00.000'),('2020-07-01T00:00:00.000'),
('2020-07-09T00:00:00.000'),('2020-07-30T00:00:00.000'),('2020-07-31T00:00:00.000')
go
create function dbo.IsWeekday(@Date date) returns bit
begin
  return case when DATEDIFF(day,'0001-01-01T00:00:00.000',@Date)
    % 7 < 5 then 1 else 0 end
end
go
create function dbo.IsHoliday(@Date date)returns bit
begin
  return case when @Date in(select Holiday from HolidayList) then 1 else 0 end
end
go
create function dbo.IsWorkDay(@Date date)returns bit
begin
  return case when dbo.IsWeekday(@Date)=1 and dbo.IsHoliday(@Date)=0 then 1 else 0 end
end
go
create function dbo.WorkdayFollowing(@Date date)returns date
begin
  declare @D date = DATEADD(day,1,@date)
  while dbo.isworkday(@D)=0 
    begin
      set @D = DATEADD(day,1,@D)
    end
  return @D
end
go



declare @d date = '2019-06-01T00:00:00.000'
while @d < '2019-09-01T00:00:00.000'
begin
  set @d=DATEADD(day,1,@d)
  select @d, dbo.workdayfollowing(@d)
end
0 голосов
/ 28 июня 2019

Спасибо, я только что использовал производный подзапрос, чтобы разрешить заполнение неправильных дат, когда должен был рассматриваться выходной, затем свернул их на другой слой и добавил дополнительный день.Не самый элегантный, но сработал по моему сценарию.

select 
 a.date 
,a.day
,a.firstOfMonth
,a.MonthName
,a.week
,a.dayofWeek
,a.hldyInd
,a.weekendInd
,case when a.Nbdtemp IN ('2020-01-01','2020-01-02','2020-01-20','2020-05-25','2020-07-03','2020-11-26','2020-12-25') then dateadd(day,1,nbdtemp) else Nbdtemp end as NxtBusinessDay
into #final
from

(
select t.*,
case when t.dayofweek not in ('Friday','Saturday') and t.HldyInd = 'N' then DATEADD(day,1,date) 
     when t.dayofweek = 'Friday' and t.hldyind = 'N' then dateadd(day,3,date) 
     when t.dayofweek = 'Saturday' and t.hldyind = 'N' then dateadd(day,2,date)  
     when t.hldyind = 'Y' then dateadd(day,1,date) end as Nbdtemp
 from #updtdim t
 ) as a
0 голосов
/ 28 июня 2019

Самый простой способ - создать таблицу праздников и вводить каждый праздник каждый год. После этого вы можете легко дать день и найти следующий рабочий день.

Вот моя функция, чтобы узнать, сколько рабочих дней между началом и концом дня. Вы можете легко изменить и получить на следующий рабочий день.

CREATE TABLE [dbo].[Holidays](
[Date] [date] NULL,
[Description] [varchar](100) NULL
) ON [PRIMARY]
GO

CREATE FUNCTION [dbo].[GetWorkingDays]
(
    @StartDate date,
    @EndDate date
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE @ResultVar int = 0;
DECLARE @dt date = @StartDate;

WHILE @EndDate >= @dt BEGIN
    IF DATEPART(WEEKDAY,@dt) < 6 BEGIN
        IF NOT EXISTS(SELECT Date FROM Holidays WHERE Date=@dt) BEGIN
            SET @ResultVar = @ResultVar + 1;
        END
    END
    SET @dt = DATEADD(DAY,1,@dt);
END 

RETURN @ResultVar;

END
0 голосов
/ 28 июня 2019

У меня нет репутации, чтобы комментировать, но из того, что я собрал ... нет, SQL Server не предоставляет функцию, но вы можете написать простую функцию, подобную той, которая сделана в этом посте Объявить дата, затем добавьте следующий рабочий день

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...