2012-06-06 49 views
0

我在我的數據庫中有一個表格「Holidays」,它包含假日期間的一系列天數,用兩列定義:開始&結束。現在如何將存儲在數據庫中的日期排除在範圍之外?

Holidays (id, name, start, end) 

,如果我有輸入,兩個日期(從&到),我想列出所有不在節假日的日期。

假設假期是從2012/06/052012/06/20,我要求:

  1. 從2012 =/06/01至= 2012/6月10日;結果將是= 01,02,03,04
  2. from = 2012/06/01,to = 2012/06/22;結果將是= 01,02,03,04,21,22
  3. from = 2012/06/15,to = 2012/06/22;其結果將是21,22

但我無法弄清楚如何獲得的「打開」天這個名單沒有擊中在範圍從 - >到每請求天數據庫。

我該怎麼辦?

感謝您的幫助!

+0

可能的重複http://stackoverflow.com/questions/5125076/sql-query-to-select-dates-between-two-dates – maksimov

回答

0

下面是我終於做到這一點,似乎工作:

SELECT start, end FROM holidays WHERE 
(start > :START AND end < :END) OR 
(start < :START AND end > :END) OR 
(start BETWEEN :START AND :END) OR 
(end BETWEEN :START AND :END); 

這將返回只有在我:START/:END日期觸摸至少一個節日的行。它涵蓋了這些可能性:

  1. 開始是前開始的假期和假期結束之前,如果結束(前中)
  2. 開始是前開始的假期,並結束後,如果假期結束(之前,之後)
  3. 開始是在假期開始之後,並且如果在假期結束之前結束(in,in)
  4. 開始於假期開始之後,並結束如果在假期結束後(在,之後)

我想我涵蓋了所有可能性。

然後我遍歷結果併爲每行建立一個從startend的日期數組。

我終於循環了我的初始範圍日期,如果其中一個日期在數組中,我將它們刪除。

0

有很多解決方案,但它很大程度上取決於您在數據庫中有多少條目以及您做了多少請求。如果你賺了很多的要求,比你可以做一些這樣的事:

-> create a boolean array that will determine if a day is holiday or not; 
    first element points to some predefined date (e.g. 1.1.2012), 
    second element to 2.1.2012, etc. 
-> initialize an array to 0 
-> for each holiday you do 
    -> make a for loop initialized with holiday start date and 
    expression for each pass: current date = holiday start date + 1 day 
    -> covert the current date to index (number of days since start date - 1.1.2012) 
    -> set the array[index] to 1 

現在,你應該有一個非節假日天含0簡單陣列和1假期天

每個查詢(請求)你現在做

-> for loop that goes from request start date to request end date 
    -> convert the current date to index (number of days since 1.1.2012) 
    -> check if array[index] is 0 or 1 

但保持在中期,這種解決方案適用於許多查詢(請求)。如果您必須爲每個請求執行第一部分,那麼比這個解決方案沒有意義,並且最好編寫一個sql查詢。

0

這裏,可以給你在一個單一的(雖然稍令人費解的)SQL語句(這是Oracle)解決方案的解決方案:

with all_days as (
    select :start_date + (level - 1) dt 
    from dual 
    connect by :start_date + (level - 1) <= :end_date 
) 
select a.dt 
    from all_days a 
where not exists (
    select 1 
     from holidays h 
    where h.start_dt <= a.dt and h.end_dt >= a.dt 
) 
order by a.dt 

例如,假設下面的假期表:

NAME   START_DT     END_DT      
-------------- ------------------------- ------------------------- 
Test Holiday 1 07-JUN-12     13-JUN-12     
Test Holiday 2 17-JUN-12     18-JUN-12     

而使用6月5日爲:start_date和6月20日爲:end_date,你會得到下面的輸出:

DT       
------------------------- 
05-JUN-12     
06-JUN-12     
14-JUN-12     
15-JUN-12     
16-JUN-12     
19-JUN-12     
20-JUN-12     

(它提供了範圍內的日期減去假期表中指定範圍內的任何日期)。

希望有所幫助。

相關問題