2017-06-26 4 views
1

私は2つのテーブルAVAILAVAIL_TIMESを持っています。 AVAILには、avail_id、avail_date、open_flagが含まれています。 AVAIL_TIMESには、avail_times_id、Avail_id、Start_Time、End_timeが含まれています。すべての日付と時刻のフィールドはDATEと入力されます他の時間の返却時間

avail open_flag列に日付がフラグされている場合は、その日付で施設が開いているが、開いている時間はavail_timesに表示されます。特定の日に複数の時間範囲が存在する可能性があります。

その日は開いていない時間のリストを返す必要があります。例については

(多くの1日)の日のための

オープン時間:

Start_time: 08:00 End_time 10:00 
Start_time: 12:00 End_time 14:00 
Start_time: 15:00 End_time 17:00 

私はそれが何か返したい:私は私のことができるようになると思い

00:00 - 07:59 
10:01 - 11:59 
14:01 - 14:59 
17:01 - 23:59 

を一時テーブルといくつかのplsqlロジックでこれを処理しますが、理想的にはこれは純粋なSQLソリューションになります。

+0

2つのテーブルの正確な構造は何ですか? 「構造」とは、列名とそのデータ型を意味します。あなたの質問に関連性がない場合は、いくつかの列を省略することができます。たとえば、テーブルにSTART_TIMEとEND_TIMEという2つの列がありますか?彼らはVARCHAR2(ひどい選択!)データ型ですか、それともDATE(完璧!)データ型ですか?次に、2番目の表で、なぜ最初の行が00:00から07:59までで08:00から始まらないようにしたいのですか?それとも10時01分から10時01分から次の1時間ですか?それは不思議で不合理です。 – mathguy

+0

すべての日付と時刻のフィールドがDATEと入力されていると編集されています。誰かがまだ8時に予約を予定することができるように、私はそれらを1分前に欲しい。私が見ているようにそれは非論理的ではありません。 08:00にオープンしていれば、なぜ08:00までそれを望んでいますか?それで解決が簡単になるのであれば、それはどういうわけか別の場所で説明する必要があります。 – JDro04

+0

時間は連続したもので、離散的なステップではありません(整数1,2,3,4など)。インターバルが00:00から07:59の間で、次のインターバルが08:00から10:00までの場合、07:59:30はどこですか? (8時の30秒前)。ほぼすべての場合、時間間隔では、1つの間隔の終わりと次の間隔の始まりとを一致させる方がずっと優れています。たとえば、単純な計算では、スペースは1日の開始時に7時間59分間表示されません。これは間違っています:8時間ではなく、7時間59分間ではありません。 – mathguy

答えて

1

興味のある日付の入力方法(私はバインド変数を使用して文字列として渡しましたが、それはあなたにとって正しい方法ではないかもしれません。テーブルなど) - またはあなたが望む正確な出力。いずれの場合でも、以下のクエリは、入力からこの種の出力を達成するために必要なコードの「コア」を示しています。

alter session set nls_date_format='mm/dd/yyyy hh24:mi'; 

with 
    avail_times (start_time, end_time) as (
     select to_date('06/20/2017 08:00'), to_date('06/20/2017 10:00') from dual union all 
     select to_date('06/20/2017 12:00'), to_date('06/20/2017 14:00') from dual union all 
     select to_date('06/20/2017 15:00'), to_date('06/20/2017 17:00') from dual 
    ) 
select trunc(min(start_time)) as start_time, min(start_time) as end_time 
    from avail_times 
    where trunc(start_time) = to_date(:input_date, 'mm/dd/yyyy') 
union all 
select end_time, 
     lead(start_time, 1, trunc(start_time) + 1) over (order by start_time) 
    from avail_times 
    where trunc(end_time) = trunc(start_time) 
order by start_time 
; 

START_TIME  END_TIME 
---------------- ---------------- 
06/20/2017 00:00 06/20/2017 08:00 
06/20/2017 10:00 06/20/2017 12:00 
06/20/2017 14:00 06/20/2017 15:00 
06/20/2017 17:00 06/21/2017 00:00 
+0

非常にクールです。ありがとうございました。それは私が必要としたものではありませんが、そこに私を連れてきます。 – JDro04

0

もう1つのアプローチ。お役に立てれば。

SELECT ID, 
    START_TME, 
    END_TM, 
    DIFF_TM 
FROM 
--Not part of SQL just to simulate the table data 
    (WITH TMP AS 
    (SELECT 1 ID, 
    TO_DATE('06/27/2017 00:00','mm/dd/yyyy hh24:mi') START_TME, 
    TO_DATE('06/27/2017 08:00','mm/dd/yyyy hh24:mi') END_TM 
    FROM DUAL 
    UNION ALL 
    SELECT 1 ID, 
    TO_DATE('06/27/2017 10:00','mm/dd/yyyy hh24:mi') START_TME, 
    TO_DATE('06/27/2017 15:00','mm/dd/yyyy hh24:mi') END_TM 
    FROM DUAL 
    UNION ALL 
    SELECT 1 ID, 
    TO_DATE('06/27/2017 16:00','mm/dd/yyyy hh24:mi') START_TME, 
    TO_DATE('06/27/2017 17:00','mm/dd/yyyy hh24:mi') END_TM 
    FROM DUAL 
    UNION ALL 
    SELECT 1 id, 
    to_date('06/27/2017 17:00','mm/dd/yyyy hh24:mi') start_tme, 
    TO_DATE('06/27/2017 18:00','mm/dd/yyyy hh24:mi') END_TM 
    FROM DUAL 
) 
    --SQL start from here 
SELECT TMP.*, 
    LEAD(START_TME) OVER(PARTITION BY ID ORDER BY 1 DESC) next_st_tm, 
    LEAD(END_TM) OVER(PARTITION BY ID ORDER BY 1 DESC) NEXT_EN_TM, 
    EXTRACT(HOUR FROM TO_TIMESTAMP(LEAD(START_TME) OVER(PARTITION BY ID ORDER BY 1 DESC),'MM/DD/YYYY HH24:MI'))- EXTRACT(HOUR FROM TO_TIMESTAMP(end_tm,'MM/DD/YYYY HH24:MI')) DIFF_TM 
FROM TMP 
ORDER BY 1 , 
    2 
) 
WHERE DIFF_TM <> 0;