2017-04-10 69 views
-3

我有一張桌子有starthour,endhour和date。 我需要的是通過sql查詢顯示可用的空閒時間和時間範圍,取決於日期。如何獲取數據庫中表格的空閒時間?

查詢只顯示沒有被佔用的自由時間。 屏幕上的輸出會是這個樣子

Date : 01/08/2017 starhour : 20:00 endhour : 21:00 duration : 60 

這是我迄今所做的:

SELECT * 
FROM (SELECT DISTINCT date, starthour, endhour 
     FROM diary 
     WHERE diary_id = 1025 
     AND date = TO_DATE('2017-05-01','yyyy/MM/dd') 
     AND (starthour >= to_timestamp('11:00:00.01','HH24:MI:SS.FF') 
     AND endhour <= to_timestamp('11:15:00.01','HH24:MI:SS.FF') 
      ) 
    ) ORDER BY date ASC, starthour ASC 
+1

,郵政您的樣本數據和預期輸出。 – Mansoor

+0

還有你到目前爲止嘗試過的。 –

+0

SELECT * FROM ( SELECT DISTINCT 日期, starthour, endhour FROM 日記 WHERE diary_id = 1025 AND 日期= TO_DATE( '2017年5月1日',「YYYY/MM/DD ') AND( starthour> = to_timestamp('11:00:00.01','HH24:MI:SS.FF') AND endhour <= to_timestamp('11:15:00.01','HH24:MI: SS.FF') ) ) 奧德R BY date ASC, starthour ASC; – Angabo

回答

0

甲骨文設置

CREATE TABLE diary ("DATE", starthour, endhour) AS 
    SELECT DATE '2017-04-10', '12:00', '12:15' FROM DUAL UNION ALL 
    SELECT DATE '2017-04-10', '12:15', '12:30' FROM DUAL UNION ALL -- Immediately follows 
    SELECT DATE '2017-04-10', '12:45', '13:15' FROM DUAL UNION ALL 
    SELECT DATE '2017-04-10', '13:00', '14:00' FROM DUAL UNION ALL -- Partly overlaps 
    SELECT DATE '2017-04-10', '14:30', '15:30' FROM DUAL UNION ALL 
    SELECT DATE '2017-04-10', '14:45', '15:15' FROM DUAL UNION ALL -- Inside previous 
    SELECT DATE '2017-04-10', '16:00', '17:00' FROM DUAL; 

查詢

WITH dates (starthour, endhour) AS (
    -- Convert your dates to include time components. 

    SELECT "DATE" + TO_DATE(starthour, 'HH24:MI') - TO_DATE('00:00', 'HH24:MI')), 
     "DATE" + TO_DATE(endhour, 'HH24:MI') - TO_DATE('00:00', 'HH24:MI')) 
    FROM diary 
    WHERE "DATE" + TO_DATE(starthour, 'HH24:MI') - TO_DATE('00:00', 'HH24:MI')) 
      < :your_end_date 
    AND "DATE" + TO_DATE(endhour, 'HH24:MI') - TO_DATE('00:00', 'HH24:MI')) 
      > :your_start_date 

    -- Add zero width entries at the start and end of the range: 

    UNION ALL SELECT :your_start_date, :your_start_date FROM DUAL 
    UNION ALL SELECT :your_end_date, :your_end_date FROM DUAL 
), 
unpivoted (datetime, isStartEnd, cnt) AS (
    -- Convert pairs of start/end times to a list of times 
    -- where the start of an appointment has a corresponding value of +1 and the 
    -- end of an appointment has a corresponding value of -1. The CNT column 
    -- is the total of all the previous +1/-1 values. 

    SELECT datetime, 
     isStartEnd, 
     SUM(isStartEnd) OVER (ORDER BY datetime ASC, isStartEnd DESC) 
    FROM dates 
    UNPIVOT (datetime FOR isStartEnd IN (starthour AS 1, endhour AS -1)) 
), 
appointment_bounds (startdate, enddate, isStartEnd) AS (
    SELECT LAG(datetime, 1) OVER (ORDER BY datetime ASC, isStartEnd DESC), 
     datetime, 
     isStartEnd 
    FROM unpivoted 
    WHERE (cnt = 0 AND isStartEnd = -1) -- Last time in a group of appointments 
    OR  (cnt = 1 AND isStartEnd = 1) -- First time in a group of appointments 
) 
SELECT startdate, 
     enddate 
FROM appointment_bounds 
WHERE isStartEnd = 1 
AND startdate IS NOT NULL; 

輸出

運行與綁定參數:your_start_date:your_end_date2017-04-10 11:00:002017-04-10 16:30:00上述查詢分別爲:

STARTDATE   ENDDATE 
------------------- ------------------- 
2017-04-10 11:00:00 2017-04-10 12:00:00 
2017-04-10 12:30:00 2017-04-10 12:45:00 
2017-04-10 14:00:00 2017-04-10 14:30:00 
2017-04-10 15:30:00 2017-04-10 16:00:00 

簡單查詢

WITH dates (starthour, endhour) AS (
    -- Convert your dates to include time components. 

    SELECT "DATE" + TO_DATE(starthour, 'HH24:MI') - TO_DATE('00:00', 'HH24:MI')), 
     "DATE" + TO_DATE(endhour, 'HH24:MI') - TO_DATE('00:00', 'HH24:MI')) 
    FROM diary 
    WHERE "DATE" + TO_DATE(starthour, 'HH24:MI') - TO_DATE('00:00', 'HH24:MI')) 
      < :your_end_date 
    AND "DATE" + TO_DATE(endhour, 'HH24:MI') - TO_DATE('00:00', 'HH24:MI')) 
      > :your_start_date 

    -- Add zero width entries at the start and end of the range: 

    UNION ALL SELECT :your_start_date, :your_start_date FROM DUAL 
    UNION ALL SELECT :your_end_date, :your_end_date FROM DUAL 
) 
SELECT prev_endhour, starthour 
FROM (
    SELECT LAG(endhour) OVER (ORDER BY starthour ASC, endhour ASC) AS prev_endhour, 
     starthour 
    FROM dates 
) 
WHERE prev_endhour < starthour;