/ / Jak mogę wykluczyć weekendy i święta w zapytaniu serwera sql - serwer sql, data

Jak wykluczyć weekendy i święta z kwerendy serwera sql - sql-server, date

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 № 1

Proponuję 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

SQL Fiddle Demo

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