2013-06-14 15 views
8

Wenn ich 2 Tage, haben, ich weiß, ich arbeiten können, wie viele Tage, Stunden, Minuten usw. sind zwischen den zwei Terminen mit datediff, zB:Überprüfen Sie, ob ein Datumsbereich ein Wochenende hat

declare @start datetime; 
set @start = '2013-06-14'; 

declare @end datetime; 
set @end = '2013-06-15'; 

select datediff(hour, @start, @end); 

Wie Ich finde heraus, ob der Zeitraum ein Wochenende umfasst?

Der Grund, warum ich wissen möchte, ob der Zeitraum ein Wochenende enthält, ist, weil ich das Wochenende von der Tages- oder Stundenzählung subtrahieren möchte. Wenn der Anfangstag Freitag ist und das Enddatum Montag ist, sollte ich nur 1 Tag oder 24 Stunden erhalten.

Datumsteil 1 = Sonntag und Datumsteil 7 = Samstag auf meinem Server.

+0

was denn nun ein „Wochenende?“ Gilt Urlaub ("dreitägige Wochenenden")? – zimdanen

+0

In diesem Fall bedeutet ein Wochenende einfach Samstag und/oder Sonntag. Ich werde die Feiertage später ausprobieren, aber nicht wichtig für diese Frage. :) – oshirowanen

+0

Zuerst, wenn der Unterschied 6 oder mehr ist, ist einer dieser Tage ein Wochenende. Wenn das Diff Null ist, müssen Sie den Wochentag für Samstag oder Sonntag überprüfen. Dann nehmen wir an, dass Sonntag der Wochentag 0 ist. Wenn der Wochentag für das Startdatum größer als der Wochentag für das Enddatum ist, hat er mindestens einen Wochenendtag im Bereich. –

Antwort

6

Ich habe eine Funktion, die Arbeitstage zwischen zwei Terminen berechnet, die grundlegende Abfrage

declare @start datetime; 
set @start = '2013-06-14'; 

declare @end datetime; 
set @end = '2013-06-17'; 
SELECT 
    (DATEDIFF(dd, @Start, @end) +1) -- total number of days (inclusive) 
    -(DATEDIFF(wk, @Start, @end) * 2) -- number of complete weekends in period 
    -- remove partial weekend days, ie if starts on sunday or ends on saturday 
    -(CASE WHEN DATENAME(dw, @Start) = 'Sunday' THEN 1 ELSE 0 END) 
    -(CASE WHEN DATENAME(dw, @end) = 'Saturday' THEN 1 ELSE 0 END) 

so können Sie arbeiten, wenn Termine Wochenende einschließen, wenn Tage anders datediff in Arbeitstagen

SELECT case when (DATEDIFF(dd, @Start, @end) +1) <> 
    (DATEDIFF(dd, @Start, @end) +1) -- total number of days (inclusive) 
    -(DATEDIFF(wk, @Start, @end) * 2) -- number of complete weekends in period 
    -- remove partial weekend days, ie if starts on sunday or ends on saturday 
    -(CASE WHEN DATENAME(dw, @Start) = 'Sunday' THEN 1 ELSE 0 END) 
    -(CASE WHEN DATENAME(dw, @end) = 'Saturday' THEN 1 ELSE 0 END) then 'Yes' else 'No' end as IncludesWeekends 

oder einfacher

SELECT (DATEDIFF(wk, @Start, @end) * 2) +(CASE WHEN DATENAME(dw, @Start) = 'Sunday' THEN 1 ELSE 0 END)  +(CASE WHEN DATENAME(dw, @end) = 'Saturday' THEN 1 ELSE 0 END) as weekendDays 
+0

Sieht aus wie die Summe der letzten 3 Begriffe gibt ihm, was er wirklich will, das ist die Anzahl der Wochenendtage im Datumsbereich enthalten. –

+2

tatsächlich SELECT (DATEDIFF (wk, @ Start, @ end) * 2) + (FALL WENN DATENAME (dw, @ Start) = 'Sonntag' DANN 1 ELSE 0 END) + (FALL WENN DATENAME (dw, @end) = 'Samstag' DANN 1 ELSE 0 ENDE) wie weekendDays sollte es tun - ich werde Antwort aktualisieren – JamieA

+0

Nice one, sehr einfach! –

3

Sie haben einen Tag am Wochenende, wenn eine der folgenden drei Bedingungen erfüllt ist:

  1. Der Tag der Woche (als ganze Zahl) des Enddatums ist kleiner als der Tag der Woche von Anfang an Datum

  2. Entweder Tag selbst ein Wochenende Tag

  3. Der Bereich mindestens sechs Tage umfasst

.

select 
    Coalesce(
    --rule 1 
    case when datepart(dw,@end) - datepart(dw,@start) < 0 then 'Weekend' else null end, 
    -- rule 2 
    -- depends on server rules for when the week starts 
    -- I think this code uses sql server defaults 
    case when datepart(dw,@end) in (1,7) or datepart(dw,@start) in (1,7) then 'Weekend' else null end, 
    --rule 3 
    -- six days is long enough 
    case when datediff(d, @start, @end) >= 6 then 'Weekend' Else null end, 
    -- default 
    'Weekday') 
+0

@LeeMeador Regel 3 ist wahr, Mi bis Mi ist 8 Tage – SQLMenace

+0

Datum Teil 1 auf meinem Server ist ein Sonntag, und 7 ist ein Samstag. – oshirowanen

+0

Die Regel wurde optimiert, um sie klarer zu machen. –

1

Eine Möglichkeit, die Sie gerade das zeigt, wie Sie eine Tabelle von Zahlen für dieses

declare @start datetime; 
set @start = '2013-06-14'; 

declare @end datetime; 
set @end = '2013-06-15'; -- play around by making this 2013-06-14 and other dates 


IF EXISTS (SELECT * FROM(
SELECT DATEADD(dd,number,@start) AS SomeDAte 
FROM master..spt_values 
WHERE type = 'P' 
AND DATEADD(dd,number,@start) BETWEEN @start AND @end) x 
WHERE DATEPART(dw,SomeDate) IN(1,7)) -- US assumed here 
SELECT 'Yes' 
ELSE 
SELECT 'No' 

Beispiel können alle Wochenenden zwischen zwei Terminen

declare @start datetime; 
set @start = '2013-06-14'; 

declare @end datetime; 
set @end = '2013-06-30'; 



SELECT DATEADD(dd,number,@start) AS SomeDAte 
FROM master..spt_values 
WHERE type = 'P' 
AND DATEADD(dd,number,@start) BETWEEN @start AND @end 
AND DATEPART(dw,DATEADD(dd,number,@start)) IN(1,7) 

Ergebnisse

2013-06-15 00:00:00.000 
2013-06-16 00:00:00.000 
2013-06-22 00:00:00.000 
2013-06-23 00:00:00.000 
2013-06-29 00:00:00.000 
2013-06-30 00:00:00.000 
0

Sie können zurückkehren Verwenden Sie folgende Funktionen. Der erste verschiebt ein bestimmtes Start- oder Enddatum auf Montag (Freitag wenn rückwärts), wenn es am Wochenende beginnt. Die Sekunde berechnet die Sekunden zwischen zwei Daten ohne Wochenenden. Dann müssen Sie nur überprüfen, ob die Gesamttage den Tagen ohne Weksends entsprechen (Demo unten).

CREATE FUNCTION [dbo].[__CorrectDate](
    @date DATETIME, 
    @forward INT 
) 

RETURNS DATETIME AS BEGIN 
    IF (DATEPART(dw, @date) > 5) BEGIN 

     IF (@forward = 1) BEGIN 
      SET @date = @date + (8 - DATEPART(dw, @date)) 
      SET @date = DateAdd(Hour, (8 - DatePart(Hour, @date)), @date) 
     END ELSE BEGIN 
      SET @date = @date - (DATEPART(dw, @date)- 5) 
      SET @date = DateAdd(Hour, (18 - DatePart(Hour, @date)), @date) 
     END 
     SET @date = DateAdd(Minute, -DatePart(Minute, @date), @date) 
     SET @date = DateAdd(Second, -DatePart(Second, @date), @date) 
    END 

    RETURN @date 
END 

GO 

CREATE FUNCTION [dbo].[__DateDiff_NoWeekends](
    @date1 DATETIME, 
    @date2 DATETIME 
) 

RETURNS INT AS BEGIN 
    DECLARE @retValue INT 

    SET @date1 = dbo.__CorrectDate(@date1, 1) 
    SET @date2 = dbo.__CorrectDate(@date2, 0) 

    IF (@date1 >= @date2) 
     SET @retValue = 0 
    ELSE BEGIN 
     DECLARE @days INT, @weekday INT 
     SET @days = DATEDIFF(d, @date1, @date2) 
     SET @weekday = DATEPART(dw, @date1) - 1 

     SET @retValue = DATEDIFF(s, @date1, @date2) - 2 * 24 * 3600 * ((@days + @weekday)/7) 
    END 

    RETURN @retValue 
END 

Dann können Sie die Informationen auf diese Weise erhalten:

declare @start datetime 
set @start = '20130614' 

declare @end datetime 
set @end = '20130615' 

declare @daysTotal int 
declare @daysWoWeekends int 

SET @daysTotal = DATEDIFF(dd, @start, @end) 
SET @daysWoWeekends = dbo.__DateDiff_NoWeekends(@start, @end)/(24 * 3600) 

SELECT CASE WHEN @daysTotal = @daysWoWeekends 
     THEN 'No weekend between' 
     ELSE 'There are weeksends' END, 
     @daysTotal, 
     @daysWoWeekends,@start,@end 

Hier ist eine Demo: http://sqlfiddle.com/#!6/7cda7/11

There are weeksends 1 0 June, 14 2013 00:00:00+0000 June, 15 2013 00:00:00+0000 
0

Hier ist die einfache und verallgemeinern Abfrage. Sie können das Ergebnis durch rekursive Abfrage erreichen. Überprüfen Sie folgende Abfrage

with mycte as 
(
    select cast('2013-06-14' as datetime) DateValue 
    union all 
    select DateValue + 1 from mycte where DateValue + 1 < '2013-06-17' 
) 

select count(*) as days , count(*)*24 as hours 
from mycte 
WHERE DATENAME(weekday ,DateValue) != 'SATURDAY' AND 
DATENAME(weekday ,DateValue) != 'SUNDAY' 
OPTION (MAXRECURSION 0) 

es wird definitiv für Sie arbeiten.

+0

Hat Ihnen das geholfen? –

0

Sie können einen rekursiven CTE verwenden die Daten zwischen dem Bereich

 WITH CTE_DatesTable 
      AS (SELECT @MinDate AS [EffectiveDate] 
       UNION ALL 
       SELECT DATEADD(dd, 1, [EffectiveDate]) 
       FROM  CTE_DatesTable 
       WHERE DATEADD(dd, 1, [EffectiveDate]) <= @MaxDate) 

      SELECT [EffectiveDate] 
      FROM CTE_DatesTable 
    OPTION (MAXRECURSION 0); 

zu bekommen und dann die Wochenenden mit filtern ..

((DATEPART(dw, DT.EffectiveDate) + @@DATEFIRST) % 7) NOT IN (0, 1) 
Verwandte Themen