2016-10-27 3 views
-2

Ich habe eine Frage und hoffentlich kann jemand helfen, weil ich auf diesem für eine lange Zeit festgefahren bin.oracle sql Zeit zu lösen Berechnung

Ich habe eine Spalte mit verbleibenden Minuten für eine Aufgabe zu verfallen und ich möchte berechnen, wenn diese Aufgabe innerhalb der Geschäftstage Zeitrahmen ab dem aktuellen Sysdate Tag abläuft, sagen wir wochentags von 09:00 bis 17:00 Uhr.

| Task No | Minutes Remaining | Expiration date | 
| Task1  | 1800    | 27-10-16 9:45 AM | 
| Task2  | 3400    | 28-10-16 9:45 AM | 
| Task3  | 400    | 29-10-16 9:45 AM | 
| Task4  | 180    | 30-10-16 9:45 AM | 
| Task5  | 8400    | 31-10-16 9:45 AM | 
| Task6  | 5000    | 1-11-16 9:45 AM | 
+0

Bitte geben Sie einige Beispieleingabedaten und was Sie die Ergebnisse zu erwarten sein. – Boneist

+0

Bitte aktualisieren Sie Ihre Frage mit den zusätzlichen Informationen. Denken Sie daran, dass wir Ihre Datenbank oder Ihre Anforderungen nicht sehen können. Daher müssen Sie so viele Informationen wie möglich zur Verfügung stellen, um Ihr Problem zu demonstrieren. – Boneist

+0

Nein, Sie müssen Ihre Frage bearbeiten (wenn Sie sich Ihre Frage ansehen, sehen Sie unterhalb der Tags 'sql' und' oracle11g' 'share edit close flag' - klicken Sie auf' edit') und fügen Sie die zusätzlichen Informationen hinzu Dort. Auf diese Weise können Sie es besser formatieren. – Boneist

Antwort

1

OK, das war ein lustiges Problem. Zusammenfassend: Sie erhalten ein Datum (in dem Oracle immer die Uhrzeit angibt), von dem aus Sie die Messung starten, sowie eine anfängliche Dauer in Minuten. Sie müssen das Ablaufdatum (wie immer Datum und Uhrzeit) finden, das berechnet wird, indem Sie die Dauer in Minuten zum Datum des Beginns der Uhr hinzufügen, aber die Uhr sollte nur während der Geschäftszeiten laufen - 9 bis 17, nur Montag bis Freitag (nicht am Wochenende).

Ich nehme an, wenn die "verbleibenden Minuten" 0 ist, dann sollte das Ablaufdatum das gleiche sein wie das "Uhr-Start" -Datum, wenn es innerhalb der Arbeitszeit fällt, oder 9 Uhr am nächsten Arbeitstag.

Um die Lösung zu verstehen, wollen wir sie in zwei Teile aufteilen. Betrachten wir zunächst einen ganz besonderen Fall: Die "Uhr beginnt" an einem Montag um 9 Uhr. Dann zerlegen Sie die verbleibenden Minuten in ein ganzzahliges Vielfaches von 2400 (5 * 8 * 60 = 2400 Minuten in einer vollen Arbeitswoche) plus ein ganzzahliges Vielfaches von 480 von dem, was übrig ist (480 Minuten zu einem Arbeitstag), plus was noch übrig ist. wenn überhaupt. Dann gilt: Das Ablaufdatum ist das "Uhr-Start" -Datum, plus viele Wochen, plus viele ganze Tage (zwischen 0 und 4) plus die restlichen Minuten. Ein Ausnahmefall hier: Wenn das "verbleibende Minuten" ein genaues Vielfaches von 480 Minuten ist, dann ist das Ablaufdatum um 17 Uhr an einem bestimmten Arbeitstag und nicht am nächsten Arbeitstag um 9 Uhr. Dies erfordert eine spezielle Handhabung in der Formel. All dies geschieht in der äußeren Abfrage (unten in der Lösung).

Dann müssen wir den allgemeinen Fall auf diesen speziellen Fall reduzieren. Dies geschieht in der Unterabfrage prep in der Lösung. Ich verlängere einfach die "verbleibenden Minuten" um die Arbeitsminuten, die am Montag um 9 Uhr am Montag zu Beginn der Woche verstrichen sind. Dies ist eine relativ einfache Berechnung. Beachten Sie, dass, wenn das Datum des "Uhrbeginns" nach 17 Uhr an einem Freitag (oder zu irgendeiner Zeit am Samstag oder Sonntag) ist, ich genau 2400 Minuten hinzufügen muss, eine volle Arbeitswoche.

In der Lösung zeige ich eine Vielzahl von "Uhr Start" Daten, dt, und noch Minuten, rm. Ich habe eine Vielzahl von Situationen getestet, und ich denke, die Lösung ist korrekt, aber Sie möchten vielleicht mehr Daten testen (andere Situationen, die ich nicht in die Tests einbezogen habe).

with 
    inputs (task, min_rem, dt) as (
select 'Task1', 1800, to_date('27-10-16 9:45 AM', 'dd-mm-yy hh:mi AM') from dual union all 
select 'Task2', 3400, to_date('28-10-16 9:45 AM', 'dd-mm-yy hh:mi AM') from dual union all 
select 'Task3', 400, to_date('29-10-16 3:45 AM', 'dd-mm-yy hh:mi AM') from dual union all 
select 'Task4', 180, to_date('30-10-16 9:45 AM', 'dd-mm-yy hh:mi AM') from dual union all 
select 'Task5', 8400, to_date('31-10-16 9:45 PM', 'dd-mm-yy hh:mi AM') from dual union all 
select 'Task6', 5000, to_date('01-11-16 5:00 PM', 'dd-mm-yy hh:mi AM') from dual union all 
select 'Task7', 0, to_date('01-12-16 5:00 PM', 'dd-mm-yy hh:mi PM') from dual 
    ), 
    prep (task, min_rem, dt, adj_min, adj_dt) as (
     select task, min_rem, dt, 
       min_rem + case when dt > trunc(dt, 'iw') + 5 + 17/24 then 2400 
          else (trunc(dt) - trunc(dt, 'iw')) * 480 + 
            least(480, greatest(0, 1440 * (dt - trunc(dt) - 9/24))) 
         end, 
       trunc(dt, 'iw') + 9/24 
    from inputs 
    ) 
select task, min_rem, dt, 
     adj_dt + 7 * trunc(adj_min/2400) 
       + case when adj_min/480 = trunc(adj_min/480) 
          then mod(adj_min, 2400)/480 - 1 + 8/24 
        else trunc(mod(adj_min, 2400)/480) + mod(adj_min, 480)/1440 
       end as expiration 
from prep 
order by task 
; 

Ausgang:

TASK  MIN_REM DT     EXPIRATION  
----- ---------- ----------------- ----------------- 
Task1  1800 27-10-16 09:45 AM 01-11-16 03:45 PM 
Task2  3400 28-10-16 09:45 AM 08-11-16 10:25 AM 
Task3  400 29-10-16 03:45 AM 31-10-16 03:40 PM 
Task4  180 30-10-16 09:45 AM 31-10-16 12:00 PM 
Task5  8400 31-10-16 09:45 PM 24-11-16 01:00 PM 
Task6  5000 01-11-16 05:00 PM 16-11-16 12:20 PM 
Task7   0 01-12-16 05:00 PM 01-12-16 05:00 PM 

7 rows selected