2017-09-21 3 views
0

この場合の週末を除外し、指定された日付の間だけに時間の差をつける方法は以下のとおりです。ウィークエンドを除外してSQLで時刻を取得

declare @d1 datetime, @d2 datetime 
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000' 

select 
    Convert(varchar(5),datediff(s, @d1, @d2)/3600 - (datediff(wk, @d1, @d2) * 2) - 
     case when datepart(dw, @d1) = 1 then 24 else 0 end + 
     case when datepart(dw, @d2) = 1 then 24 else 0 end) 
     +':'+ 
     convert(Varchar(5),datediff(s, @d1, @d2)%3600/60 - (datediff(wk, @d1, @d2) * 2) - 
     case when datepart(dw, @d1) = 1 then 24 else 0 end + 
     case when datepart(dw, @d2) = 1 then 24 else 0 end) 
      +':'+ 
     convert(Varchar(5),datediff(s, @d1, @d2)%60 - (datediff(wk, @d1, @d2) * 2) - 
     case when datepart(dw, @d1) = 1 then 24 else 0 end + 
     case when datepart(dw, @d2) = 1 then 24 else 0 end 
     ) as hrs 
+0

「週末」とは、実際に「休業日」を意味しましたか?それらは同じものではないからです。そして、自然災害が報道されているので、「標準的な」就業日であっても実際には「働いていない」と考えてください。これをどうやって解決しますか?インターネットで「カレンダーテーブル」を検索します。 – SMor

答えて

0

ひとつのアイデアは、@ d2の前に@ d1と前月曜日以降に最初の月曜日を(私たちは「週末」は土日を意味することを言っている場合)を見つけることです。これは一週間の数です。だから一週間の時間は120(5日* 24時間)です。それから、最後の月曜日から@ d2までの時間を追加します。 @ d2の曜日の単純なケースでは、この先週の週末を世話することができます。同様に、@ d1と最初の月曜日の間の時間を数えます。

declare @d1 datetime, @d2 datetime 
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000' 

declare @StartOfFirstWeekAfterStartDate date = cast(dateadd(day, case datepart(weekday, @d1) 
    when 1 /* Sunday */ then -6 
    when 2 /* Monday */ then 0 
    when 3 /* Tuesday */ then 6 
    when 4 /* Wendsday */ then 5 
    when 5 /* Thursday */ then 4 
    when 6 /* Friday */ then 3 
    when 7 /* Saturday */ then 2 
    end, @d1) as date), 
    @StartOfLastWeekBeforeEndDate date = cast(dateadd(day, case datepart(weekday, @d2) 
    when 1 /* Sunday */ then -6 
    when 2 /* Monday */ then 0 
    when 3 /* Tuesday */ then -1 
    when 4 /* Wendsday */ then -2 
    when 5 /* Thursday */ then -3 
    when 6 /* Friday */ then -4 
    when 7 /* Saturday */ then -5 
    end, @d2) as date) 

declare @NumberOfWorkdays int = datediff(week, @StartOfFirstWeekAfterStartDate, @StartOfLastWeekBeforeEndDate) * 5 

declare @HoursWeekBefore int = case datepart(weekday, @d1) 
    when 1 /* Sunday */ then 0 
    when 2 /* Monday */ then 5 * 24 - datepart(hour, @d1) 
    when 3 /* Tuesday */ then 4 * 24 - datepart(hour, @d1) 
    when 4 /* Wendsday */ then 3 * 24 - datepart(hour, @d1) 
    when 5 /* Thursday */ then 2 * 24 - datepart(hour, @d1) 
    when 6 /* Friday */ then 1 * 24 - datepart(hour, @d1) 
    when 7 /* Saturday */ then 0 
    end 

declare @HoursWeekAfter int = case datepart(weekday, @d2) 
    when 1 /* Sunday */ then 5 * 24 
    when 2 /* Monday */ then 0 * 24 + datepart(hour, @d2) 
    when 3 /* Tuesday */ then 1 * 24 + datepart(hour, @d2) 
    when 4 /* Wendsday */ then 2 * 24 + datepart(hour, @d2) 
    when 5 /* Thursday */ then 3 * 24 + datepart(hour, @d2) 
    when 6 /* Friday */ then 4 * 24 + datepart(hour, @d2) 
    when 7 /* Saturday */ then 5 * 24 
    end 

declare @HoursDiff int = @HoursWeekBefore + @NumberOfWorkdays * 24 + @HoursWeekAfter 

select 
    @StartOfFirstWeekAfterStartDate, 
    datepart(WEEKDAY, @StartOfFirstWeekAfterStartDate), -- Should always be Monday 
    @StartOfLastWeekBeforeEndDate, 
    datepart(WEEKDAY, @StartOfLastWeekBeforeEndDate), -- Should always be Monday 
    @NumberOfWorkdays, 
    datediff(week, @StartOfFirstWeekAfterStartDate, @StartOfLastWeekBeforeEndDate), 
    @HoursWeekBefore, 
    @HoursWeekAfter, 
    @HoursDiff 

上記のコードは、sp/udfの使用に適しています。

declare @d1 datetime, @d2 datetime 
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000' 

select case datepart(weekday, @d1) 
    when 1 /* Sunday */ then 0 
    when 2 /* Monday */ then 5 * 24 - datepart(hour, @d1) 
    when 3 /* Tuesday */ then 4 * 24 - datepart(hour, @d1) 
    when 4 /* Wendsday */ then 3 * 24 - datepart(hour, @d1) 
    when 5 /* Thursday */ then 2 * 24 - datepart(hour, @d1) 
    when 6 /* Friday */ then 1 * 24 - datepart(hour, @d1) 
    when 7 /* Saturday */ then 0 
    end /* @HoursWeekBefore */ 
    + 
    datediff(week, 
     cast(dateadd(day, case datepart(weekday, @d1) 
      when 1 /* Sunday */ then -6 
      when 2 /* Monday */ then 0 
      when 3 /* Tuesday */ then 6 
      when 4 /* Wendsday */ then 5 
      when 5 /* Thursday */ then 4 
      when 6 /* Friday */ then 3 
      when 7 /* Saturday */ then 2 
      end, @d1) as date) /* @StartOfFirstWeekAfterStartDate */, 
     cast(dateadd(day, case datepart(weekday, @d2) 
      when 1 /* Sunday */ then -6 
      when 2 /* Monday */ then 0 
      when 3 /* Tuesday */ then -1 
      when 4 /* Wendsday */ then -2 
      when 5 /* Thursday */ then -3 
      when 6 /* Friday */ then -4 
      when 7 /* Saturday */ then -5 
      end, @d2) as date) /* @StartOfLastWeekBeforeEndDate */) * 5 /* @NumberOfWorkdays */ * 24 
    + 
    case datepart(weekday, @d2) 
     when 1 /* Sunday */ then 5 * 24 
     when 2 /* Monday */ then 0 * 24 + datepart(hour, @d2) 
     when 3 /* Tuesday */ then 1 * 24 + datepart(hour, @d2) 
     when 4 /* Wendsday */ then 2 * 24 + datepart(hour, @d2) 
     when 5 /* Thursday */ then 3 * 24 + datepart(hour, @d2) 
     when 6 /* Friday */ then 4 * 24 + datepart(hour, @d2) 
     when 7 /* Saturday */ then 5 * 24 
     end /* @HoursWeekAfter */ 

、上記の計算は、DATEFIRST設定に依存しませてくださいということ:我々は、単一の式にすべてのこれらの計算を置く場合は、このなります。私は、日曜日が週の最初の曜日であるという前提で書いています(すなわち、datepart(平日、@Moday)は2を返します)。そうでない場合は、case文のオフセットを調整する必要があります。 また、私はこれらの時間に分を処理しなかったので、時間計算は少し粗いです。これが問題である場合は、@ d1の間とd2 @分の数を計算し、これは、私は機能(に類似)で60

+0

この点で私を助けてくれたAndrey Nikolovに感謝します。しかし、土曜日は今週の最初の日です。それに応じて修正し、私を助けることが可能ですか?私はこれらのコーディングでは新しいので、コードの変更を要求しています。 –

+0

**このクエリの先頭に** DATEFIRST 7 **を追加するか(週の最初の日を日曜日に変更する)か、case文の数値を変更するかのいずれかである必要があります。** datepart(平日)**は日曜日は2、月曜日は3、火曜日は4、水曜日は5、木曜日は6、金曜日は7、土曜日は1になります。 –

0
create function DateDiffWeekends(@a date, @b date) 
returns int as 
BEGIN 
DECLARE @Result int 
SELECT @Result = DateDiff(dd,@a,@b) 
       - DateDiff(ww,@a,@b)*2 
       - case DatePart(dw,@a) when 1 then 1 else 0 end 
       - case DatePart(dw,@b) when 7 then 1 else 0 end 
RETURN @Result 
End 

ことによって、これを分割するために、上記の方法を使用することができますプロダクション環境を使用します。私はSELECT @Resultエリアの4つの式のそれぞれが何をしているのかを解説します。

DateDiff(dd,@a,@b) 

これは、単に2つの日付の間の日数を特定することです。クラシックDateDiff。

- DateDiff(ww,@a,@b)*2 

これにより、2日間の週数が検出され、2が乗算されます。この理由は、「7日間のセグメント」の数ではなく、週休憩の回数をカウントしているためです。たとえば、金曜日とその次の月曜日の日付を選択すると、DateDiff(ww,$Saturday,$Monday)は技術的に2日間離れていても1週間返されます。

- case DatePart(dw,@a) when 1 then 1 else 0 end 

日曜日の開始日を選択した場合は、結果からもう1日休暇を取る必要があります。あなたの開始日が土曜日の場合、それは別の週になるので、前のステートメントがそれを処理します。

- case DatePart(dw,@b) when 7 then 1 else 0 end 

土曜日の終了日を選択した場合は、その結果から1日を取る必要があります。あなたの終わりの日が日曜日であれば、再び別の週になるでしょう。

テスト/再生したい場合は、SQLFiddleです。

編集:あなたも時間を求めていることに気付きました。他の人にとって役に立つ場合に備えて、この回答を残しておきますが、あなたのケースではうまくいかないかもしれません。

関連する問題