Tworzę zapytanie, które dostosuje datę z wyłączeniem świąt i weekendów.
Przykładowe dane:
Adjusted Date | Adjusted Date(Excluding Holidays and weekends)
02/06/16 | 02/09/16
Na moim przykładzie data to weekend i dostosowanadata zmienia się na 9 lutego, ponieważ 8 lutego to święto, więc musi się dostosować, aby data dostosowania była dniem roboczym. Obecnie mam oddzielną tabelę wszystkich weekendów i świąt w roku podatkowym.
select case when (
select count(dbo.WeekendsHoliday.[Weekends & Holidays])
from dbo.WeekendsHoliday
where dbo.WeekendsHoliday.[Weekends & Holidays]
= case when convert(time, [Time Received]) > convert(time, "5:00:00 PM")
then dateadd(day, 1, [Date Received])
else [Date Received]
end
) > 0
then case (datename(DW,
case when convert(time, [Time Received]) > convert(time, "5:00:00 PM")
then dateadd(day, 1, [Date Received])
else [Date Received]
end))
when "Saturday"
then dateadd(day, 2,
case when convert(time, [Time Received]) > convert(time, "5:00:00 PM")
then dateadd(day, 1, [Date Received])
else [Date Received]
end)
else dateadd(day, 1,
case when convert(time, [Time Received]) > convert(time, "5:00:00 PM")
then dateadd(day, 1, [Date Received])
else [Date Received]
end)
end
end as [Adjusted Date Excluding holidays and weekends]
Dzieje się tak, jeśli święto przypada na 2 kolejne dni (czwartek i piątek), data dostosowania to sobota, która nadal nie jest ważna, ponieważ jest to weekend.
Skorygowana data jest tutaj aliasem
Ja naprawdę potrzebuję Twojej pomocy. Dzięki
Odpowiedzi:
2 dla odpowiedzi № 1Proponuję stworzyć funkcję rekurencyjnąsprawdź następny dzień roboczy na podstawie tabeli zawierającej weekendy i święta. Zaletą tego podejścia jest to, że jest to funkcja wielokrotnego użytku, gdy jej potrzebujesz.
Ta funkcja odbiera datę i godzinę. (Na podstawie kodu podanego w pytaniu), jeśli czas przypada po godzinie 17:00, dodaje dzień. Po, kontynuuje sprawdzanie, czy data nie jest w weekendy lub święta, dopóki nie znajdzie następnego dnia roboczego:
CREATE FUNCTION dbo.adjustedDate(@dateReceived DATETIME, @timeReceived TIME)
RETURNS DATETIME
AS
BEGIN
DECLARE @adjustedDate DATETIME = @dateReceived
-- Verify time to add 1 day to @adjustedDate
IF @timeReceived IS NOT NULL
IF @timeReceived > CONVERT(TIME, "5:00:00 PM")
SET @adjustedDate = DATEADD(DAY, 1, @adjustedDate)
-- Continue adding 1 day to @adjustedDate recursively until find one date that is not a weekend or holiday
IF EXISTS(SELECT [Weekends & Holidays]
FROM dbo.WeekendsHoliday
WHERE [Weekends & Holidays] = @adjustedDate)
SET @adjustedDate = dbo.adjustedDate(DATEADD(DAY, 1, @adjustedDate), NULL)
RETURN @adjustedDate
END
2 dla odpowiedzi nr 2
zajmuje to daty w tabeli Weekends Holiday i znajduje następny dzień, który nie znajduje się w tej samej tabeli.
następnie połączyłeś się z wynikiem, aby uzyskać „Następny dzień”, jeśli data z tabeli znajduje się w tabeli WeekendsHoliday
DECLARE @WeekendsHoliday TABLE ([Weekends & Holidays] DATETIME)
INSERT INTO @WeekendsHoliday VALUES
("2016-03-05"),
("2016-03-06"),
("2016-03-07"),
("2016-03-12"),
("2016-03-13");
DECLARE @Schedule TABLE ([WorkDay] DATETIME)
INSERT INTO @Schedule VALUES
("2016-03-02"),
("2016-03-03"),
("2016-03-05"),
("2016-03-07"),
("2016-03-08"),
("2016-03-11"),
("2016-03-12");
WITH RecursiveCTE AS
(
SELECT
[Weekends & Holidays],
DATEADD(d, 1, [Weekends & Holidays]) AS [Next Day]
FROM
@WeekendsHoliday
UNION ALL
SELECT
cte.[Weekends & Holidays],
DATEADD(d, 1, [Next Day])
FROM
RecursiveCTE cte
WHERE
[Next Day] IN (SELECT [Weekends & Holidays] FROM @WeekendsHoliday)
),
AggregateCTE AS (
SELECT
[Weekends & Holidays],
MAX([Next Day]) [Next Day]
FROM
RecursiveCTE
GROUP BY
[Weekends & Holidays]
)
SELECT
s.WorkDay,
COALESCE(cte.[Next Day], s.WorkDay) AS [Adjusted Date Excluding holidays and weekends]
FROM
@Schedule s
LEFT JOIN AggregateCTE cte ON s.[WorkDay] = cte.[Weekends & Holidays]
używasz INNER JOIN AggregateCTE
zamiast LEFT JOIN AggregateCTE
jeśli chcesz zobaczyć tylko daty, które są dostosowane. Polecam także filtrowanie WITH RecursiveCTE
według daty rozpoczęcia i zakresu daty końcowej, jeśli to możliwe.
2 dla odpowiedzi nr 3
SELECT MIN(allDays.dte)
FROM (
SELECT "2015-01-01" + INTERVAL ones.a + 10*tens.a + 100*hundred.a DAY dte
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) ones,
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) tens,
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) hundred
WHERE "2015-01-01" + INTERVAL ones.a + 10*tens.a + 100*hundred.a DAY < "2016-01-01"
) allDays
LEFT JOIN holidays H
ON allDays.dte = H.holydate
WHERE
H.holydate IS NULL
AND allDays.dte >= "2015-12-12" -- HERE go your Source DATE
WYDAJNOŚĆ
| MIN(allDays.dte) |
|------------------|
| 2015-12-14 | --Because 12 and 13 are holidays
WYJAŚNIAĆ
Najpierw musisz utworzyć listę na wszystkie dni. Tutaj generuję podkwerendę, aby wyświetlić wszystkie dni od 2015
, będziesz musiał dostosować się do dużych zakresów.
SELECT "2015-01-01" + INTERVAL ones.a + 10*tens.a + 100*hundred.a DAY dte
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) ones,
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) tens,
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) hundred
WHERE "2015-01-01" + INTERVAL ones.a + 10*tens.a + 100*hundred.a DAY < "2016-01-01"
Potem wykonujesz left join
aby sprawdzić, czy DATA jest świętem
LEFT JOIN holidays H
ON allDays.dte = H.holydate
Na koniec wybierz mniejszą datę, która nie jest świętem
WHERE H.holydate IS NULL -- NULL mean doesnt have a match in the holiday table
AND allDays.dte >= "2015-12-12" -- HERE go your Source DATE
1 dla odpowiedzi nr 4
Stworzyłem bardzo prosty kod, który będziewyklucz wakacje i sobotę niedzielę, dodając dni do daty. Najpierw musisz stworzyć świąteczny stół, a następnie możesz skorzystać z poniższego kodu. Mam nadzieję, że otrzymasz wynik z moim kodem, ponieważ stworzyłem go i działa poprawnie.
;WITH Numbers AS
(
SELECT 1 AS value
UNION ALL
SELECT value + 1 AS value
FROM Numbers
WHERE Numbers.value <= 99
)
SELECT FinalTable.FromDate,FinalTable.AddedDays,FinalTable.AdjustedDate
FROM (
SELECT Final.*,ROW_Number() OVER (ORDER BY (SELECT NULL)) AS AddedDays
FROM (
SELECT tbl.FromDate,CASE WHEN DATENAME(dw,tbl.AdjustedDate) = "Saturday" THEN 0
WHEN DATENAME(dw,tbl.AdjustedDate) = "Sunday" THEN 0
WHEN tbl.AdjustedDate in (SELECT Holiday_Date FROM Holiday) THEN 0
ELSE 1 END AS LogicNumber ,tbl.days, tbl.AdjustedDate
FROM (
SELECT @FromDate AS FromDate, DATEADD(DAY,num,@FromDate) AS AdjustedDate, num AS days
FROM (
SELECT ROW_Number() OVER (ORDER BY (SELECT NULL)) AS num FROM Numbers
) t
WHERE num <= 100
) tbl
)Final
WHERE LogicNumber = 1
)FinalTable
WHERE AddedDays = @days
Pozwala powiedzieć @romdate = "2017-12-30" I 1 stycznia 2018 r. To święto, które jest obecne w świątecznym stole i musimy dodać 10 dni, tj. @ Dni = 10
WYDAJNOŚĆ
FromDate | AddedDays | AdjustedDate
2017-12-30 | 10 | 2018-01-15