2017-04-21 17 views
0

Ich muss Datensätze finden, die seit dem letzten Schichtbeginn geändert wurden. Verschiebungen beginnen um 07: 00h (morgens), 15: 00h (nachmittags) und 23: 00h (nachts).SQL Server den nächsten Schichtbeginn (Zeit) zu einem Datum finden

Zum Beispiel. Es ist jetzt 17: 15h, also bin ich in der Nachmittagsschicht. Jetzt möchte ich arbeitsbezogene Datensätze finden, die seit Beginn meiner vorherigen Schicht geändert wurden. Also brauche ich eine Startzeit von 15:00 am Vortag. Das ist seit 24 Stunden + die Zeit in der aktuellen Schicht.

Ich brauche eine Lösung, die ich als Teil einer Where-Klausel implementieren kann.

Grundsätzlich versuche ich den letzten Beginn einer Schicht zu finden (7, 15 oder 23h) und subtrahiere dann weitere 24 Stunden von diesem Datum. Und lassen Sie die Abfrage bis zur aktuellen Zeit laufen.

select * from workorder 
where changedate >= getDate() - 24h - time_in_shift 

oder

select * from workorder 
where changedate >= last_shift_start - 24h 

Um ehrlich zu sein, ich habe nicht eine gute Strategie noch nicht gefunden. Zuerst habe ich versucht, die richtige Verschiebung mit einer Case-Anweisung zu finden und diese für die korrekte Berechnung zu verwenden. Aber ich denke nicht, dass dies der beste Weg ist.

select getDate() as now, 
case 
    when datepart(hh, getDate())-23 >= 0 then 'night' 
    when datepart(hh, getDate())-15 >= 0 then 'afternoon' 
    when datepart(hh, getDate())-7 >= 0 then 'morning' 
    else 'night' 
end as shift; 

Hier einige Beispieldaten

id changedate 
1 '2017-04-20 01:00:00' 
2 '2017-04-20 02:00:00' 
3 '2017-04-20 08:00:00' 
4 '2017-04-20 09:00:00' 
5 '2017-04-20 14:00:00' 
6 '2017-04-20 16:00:00' 
7 '2017-04-20 17:00:00' 
8 '2017-04-20 22:00:00' 
9 '2017-04-20 23:00:00' 
10 '2017-04-20 23:30:00' 
11 '2017-04-21 01:10:00' 
12 '2017-04-21 02:10:00' 
13 '2017-04-21 08:10:00' 
14 '2017-04-21 10:10:00' 
15 '2017-04-21 16:10:00' 
16 '2017-04-21 16:20:00' 

Können sagen, es 2017.04.21 17.00.00 jetzt ist. Ich bin also in der Nachmittagsschicht. Das bedeutet, ich möchte alle Datensätze, die seit meinem vorherigen Start geändert wurden. Also seit 2017-04-20 15:00:00. Das sind alle Datensätze mit Ausnahme der ersten 5.

+2

erläutert bitte einige Beispieldaten und die erwartete Ausgabe. –

+0

planen Sie, die Startzeit der Schicht zu programmieren und 24 Stunden zurückzuschauen? –

+0

ja, es ist für eine konfigurierbare Ergebnisabfrage, so ziemlich zugänglich und wahrscheinlich sowieso nicht zu ändern – Jeroen

Antwort

1

Wenn Sie SQL Server 2012 verwenden, können Sie Ihre WHERE Klausel mit einer case-Anweisung bauen:

select * 
from workorder 
where changedate >= case 
      when datepart(hh, getDate()) >= 23 
       then smalldatetimefromparts(year(dateadd(day, -1, cast(getdate() as date))), 
              month(dateadd(day, -1, cast(getdate() as date))), 
              day(dateadd(day, -1, cast(getdate() as date))), 
              23, 00) 
      when datepart(hh, getDate()) < 7 
       then smalldatetimefromparts(year(dateadd(day, -2, cast(getdate() as date))), 
              month(dateadd(day, -2, cast(getdate() as date))), 
              day(dateadd(day, -2, cast(getdate() as date))), 
              23, 00) 
      when datepart(hh, getDate()) between 15 and 22 
       then smalldatetimefromparts(year(dateadd(day, -1, cast(getdate() as date))), 
              month(dateadd(day, -1, cast(getdate() as date))), 
              day(dateadd(day, -1, cast(getdate() as date))), 
              15, 00) 
      else smalldatetimefromparts(year(dateadd(day, -1, cast(getdate() as date))), 
             month(dateadd(day, -1, cast(getdate() as date))), 
             day(dateadd(day, -1, cast(getdate() as date))), 
             7, 00) 
     end; 

Wenn Sie Wenn Sie eine ältere Version von SQL Server verwenden, können Sie dasselbe mit einer expliziten Konvertierung durchführen, indem Sie smalldatetimefromparts ersetzen. Sie können es in this answer

+0

Das Erstellen einer Datetime mit 'getDate() - 1' schlägt am ersten Tag eines Monats fehl. –

+0

Sie haben Recht, danke. ich habe es repariert –

1

Zunächst ist eine Tabelle für die Verschiebungen (mit nur einer Spalte). Natürlich können Sie dies auch on-the-fly generieren, aber warum nicht in Ihrer Datenbank?

 
shiftstart 
07:00 
15:00 
23:00 

Um die aktuelle Verschiebung zu erhalten, können Sie etwas tun:

select 
    coaleasce 
    (
    max(case when shiftstart < cast(getdate() as time) then shiftstart end), 
    max(shiftstart) 
) 
from shift; 

gestern Fügen Sie die shiftstart für gestern zu bekommen:

dateadd(day, -1, cast(getdate() as date)) + <above time> 

UPDATE: Wie Damien_The_Unbeliever zu Recht darauf hingewiesen:

wenn es zur Zeit 02.00 ist, wollen wir alles nach 23:00 Uhr von zwei Tagen

So wir entweder ein Tag oder zwei in Abhängigkeit von der Zeit abziehen müssen.


Die vollständige angepasste Abfrage:

select * 
from workorder 
where changedate >= 
(
    select 
    coaleasce 
    (
     dateadd(day, -1, cast(getdate() as date)) + 
     max(case when shiftstart < cast(getdate() as time) then shiftstart end), 
     dateadd(day, -2, cast(getdate() as date)) + 
     max(shiftstart) 
    ) 
    from shift 
); 
Verwandte Themen