2017-06-26 27 views
1

我有兩個表AVAILAVAIL_TIMESAVAIL包含avail_id,avail_date,open_flag。 AVAIL_TIMES包含avail_times_id,Avail_id,Start_Time,End_time。所有日期和時間字段都鍵入日期其他時間之間的返回時間

如果在open_flag列中標記日期,則表示該設施在該日期處於打開狀態,但打開的時間列於avail_times。特定日期可能有多個時間範圍。

我需要返回它當天未打開的列表。

爲例(許多的一天)

白天開放時間:

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

這兩張表的確切結構是什麼? 「結構」是指列名稱及其數據類型。如果他們與你的問題沒有關係,你可以省略一些專欄。因此,例如:表中有兩列,START_TIME和END_TIME?他們是VARCHAR2(糟糕的選擇!)數據類型,還是他們是DATE(完美!)數據類型?然後:在第二個表格中,爲什麼要讓第一行從00:00到07:59而不是08:00?或者從10:01開始下一個,而不是從10:00開始?這很奇怪,不合邏輯。 – mathguy

+0

編輯爲說所有日期和時間字段都輸入爲DATE。我希望他們在一分鐘之前,以便有人仍然可以在8:00安排預約。我看到它並不是不合邏輯的。如果08:00開放,我爲什麼要在08:00之前使用它?如果這樣可以讓解決方案更簡單,那麼就可以,但我必須在其他地方以某種方式解釋它。 – JDro04

+0

時間是連續的,而不是離散的步驟(如整數1,2,3,4 ...)。如果間隔時間爲00:00至07:59,下一個時間爲08:00至10:00,07:59:30哪裏下降? (8點前30秒)。在幾乎所有情況下,按照時間間隔,匹配一個間隔的結束和下一個間隔的開始會更好。例如:在一個簡單的計算中,您將顯示該空間在一天的開始時間不可用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

另一種方法。希望這可以幫助。

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;