1

SQL Server 2008 R2を使用して、従業員の夜間のシフト時間を選択する方法を探しています。この場合は22.00と6.00+1です。

私たちの問題は、シフトが真夜中を横切る時間を取得する方法、またはシフトが05.30から22.30に始まり、シフトの開始と終了の両方でオーバーラップするときにオーバーラップを取得する方法になります。

次に例を示します。これらはデータベースで利用可能なデータであり、私たちが探している結果です。

        startDateTime     |       endDateTime         |   nightHours
--------------------------+---------------------------+----------------
 2012-07-04 05:00:00.000    2012-07-04 23:00:00.000          2 
 2012-07-04 18:00:00.000    2012-07-05 05:00:00.000          7

誰かが私たちが使用できる例またはいくつかの良いポインタを持っていますか?

4

2 に答える 2

2

これは非常に複雑かもしれませんが、機能します。いくつかのCTEを使用して、有用な中間表現を構築します。

declare @Times table (
    ID int not null,
    StartTime datetime not null,
    EndTime datetime not null
)
insert into @Times (ID,StartTime,EndTime)
select 1,'2012-07-04T05:00:00.000','2012-07-04T23:00:00.000' union all
select 2,'2012-07-04T18:00:00.000','2012-07-05T05:00:00.000'

;With Start as (
    select MIN(DATEADD(day,DATEDIFF(day,0,StartTime),0)) as StartDay from @Times
), Ends as (
    select MAX(EndTime) EndTime from @Times
), Nights as (
    select DATEADD(hour,-2,StartDay) as NightStart,DATEADD(hour,6,StartDay) as NightEnd from Start
    union all
    select DATEADD(DAY,1,NightStart),DATEADD(DAY,1,NightEnd) from Nights n
    inner join Ends e on n.NightStart < e.EndTime
), Overlaps as (
    select
        t.ID,
        CASE WHEN n.NightStart > t.StartTime THEN n.NightStart ELSE t.StartTime END as StartPeriod,
        CASE WHEN n.NightEnd < t.EndTime THEN n.NightEnd ELSE t.EndTime END as EndPeriod
    from
        @Times t
            inner join
        Nights n
            on
                t.EndTime > n.NightStart and
                t.StartTime < n.NightEnd
), Totals as (
    select ID,SUM(DATEDIFF(hour,StartPeriod,EndPeriod)) as TotalHours
    from Overlaps
    group by ID
)
select
    *
from
    @Times t
        inner join
    Totals tot
        on
            t.ID = tot.ID

結果:

ID          StartTime               EndTime                 ID          TotalHours
----------- ----------------------- ----------------------- ----------- -----------
1           2012-07-04 05:00:00.000 2012-07-04 23:00:00.000 1           2
2           2012-07-04 18:00:00.000 2012-07-05 05:00:00.000 2           7

ID相関関係を機能させるには、列を追加する必要があることに注意してください。

StartCTEは、該当する最も早い深夜を見つけます。EndCTEは、重複する夜を見つける必要がある最後の時間を見つけます。次に、再帰NightsCTEは、これら2つの時点の間で毎晩計算します。次に、これを元のテーブル(in Overlaps)に結合して、各夜に適用される期間を見つけます。最後に、ではTotals、重複する各期間が何時間寄与したかを計算します。

これは、複数日のイベントで機能するはずです。Totals部分時間をカウントする必要がある場合は、分を使用するようにCTEを変更するか、他の丸め関数を適用することをお勧めします。

于 2012-07-04T09:29:54.593 に答える
0

最善の方法は、シフトの開始時間と終了時間を取る関数だと思います。次に、関数内に 2 つのケースがあります。1 つ目は、シフトが同じ日に開始および終了する場合、もう 1 つのケースは、ある日に開始して次の日に終了する場合です。

開始と終了が同じ日の場合

@TotalOvernightHours=0 

@AMDifference = Datediff(hh, @shiftStart, @6amOnThatDay);
if @AMDIfference > 0 than @TotalOvernightHours = @TotalOvernightHours + @AMDifference

@PMDifference Datediff(hh, @10pmOnThatDay, @ShiftEnd)
if @PMDifference > 0 than @TotalOvernightHours = @TotalOvernightHours + @PMDifference

開始日と終了日が異なる場合は、2 シフトのふりをします。最初は @ShiftStart に開始しますが、午前 0 時に終了します。2 つ目は午前 0 時に開始し、@ShiftEnd に終了します。そして、シフトごとに上記のロジックを適用してください。

24 時間以上のシフトがある場合は、午前 0 時を境に小さなサブシフトに分割します。したがって、シフトが で開始して1 Jun 19:00で終了 3 Jun 5:00する場合、3 つのサブシフトになります。

  • 6 月 1 日 19:00 - 6 月 1 日 24:00
  • 6 月 2 日 00:00 - 6 月 2 日 24:00
  • 6 月 3 日 00:00 - 6 月 3 日 5:00

そして、すべてのサブシフトについて、夜通しの時間を計算します。

おそらく、1 つの 24 時間の夜間勤務時間を計算する関数と、シフト全体を 24 時間のチャンクに分割して最初の関数にフィードする別の関数を作成するでしょう。

psこれはSQLではなく、疑似コードのみです。pps これは、関数を作成できる場合にのみ機能します。そして、クリーンで簡単に準備できるコードが得られます。

于 2012-07-04T09:39:08.407 に答える