これは楽しい問題でした。要約すると、測定を開始する日付(Oracleには常に時刻が含まれています)と、最初の時間(分)が与えられます。有効期限(日時はいつもと同じです)を見つける必要があります。これは「時計開始日」に分数を加えて計算されますが、時計は営業時間内にのみ実行する必要があります。 17、月曜日から金曜日のみ(週末は除く)。
「残りの分」が0の場合、有効期限は就業時間内にある場合は「時計始動」日付と同じでなければなりません。そうでない場合は翌営業日に午前9時です。
解決策を理解するには、2つの部分に分解しましょう。まず、非常に特殊なケースを考えましょう。月曜日の午前9時に「時計が始まります」。次に、2400の整数倍(1週間に5 * 8 * 60 = 2400分)に残りの分を加え、残りの分(480分〜作業日)から480の倍数に加えて、もしあれば。次に、有効期限は「時計始動」の日付に加えて、数週間に加えて多くの終日(0と4の間)に加えて残りの分を加えたものです。 1つの例外的な場合:「残りの分」が480分の正確な倍数である場合、有効期限は特定の就業日に午後5時であり、翌営業日に午前9時ではない。これには、数式で特別な処理が必要です。このすべては外側のクエリ(以下のソリューションの一番下)で行われます。
次に、この特殊なケースに一般的なケースを減らす必要があります。これは、ソリューション内のサブクエリprep
で行われます。私は週の初めに月曜日の午前9時から経過した作業分だけ「残りの分」を増やします。これは比較的単純な計算です。 「時計開始」の日付が金曜日の午後5時(または土曜日または日曜日の午後)の後である場合は、2400分(フルワーキング週間)を追加する必要があります。
解決策では、さまざまな「クロック開始」日付、dt
、残りの分数はrm
です。私はさまざまな状況をテストしましたが、解決策は正しいと思いますが、より多くのデータをテストすることができます(私がテストに含まなかった他の状況)。
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
;
出力:
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
いくつかのサンプルの入力データとどのようなあなたは結果があることを期待しているを入力してください。 – Boneist
質問を追加情報で更新してください。データベースや要件を見ることができないので、問題を実証するためにできるだけ多くの情報を提供する必要があります。 – Boneist
いいえ、あなたの質問を編集する必要があります( 'sql'と' oracle11g'タグの下にあなたの質問を見るなら、 'edit edit'をクリックして'そこ。そうすれば、あなたはそれをより良くフォーマットすることができます。 – Boneist