2009-04-22 179 views
3

我已經從這個拿到了下一個問題了:Comparing date ranges比較兩個日期範圍時一個範圍內有一個範圍開始日期

的解決方案,比較兩個範圍是查詢:

SELECT * 從時間 WHERE NOT(RANGE_START> @check_period_end OR RANGE_END < @check_period_start)

我有額外的問題。我允許人們輸入一段時間。準確地說,他們輸入一個持續時間(即1周)和一系列開始日期(即5月的前2周),我必須找出他們指定的範圍內是否有一週的時間段。

天真的解決方案是在我的範圍內每天運行上述查詢。因此 - 爲了檢查一個月內的3天插槽,我必須運行30個查詢。有沒有更高效的方法?

對於獎勵積分 - 我正在使用Django。使用Django ORM有沒有好的解決方案?

編輯 - 爲了簡化問題,我想我已經把它變成了另一個問題!我的實際問題是找到'自由空白'。我認爲這會使下面的一些'純SQL'方法無效。我認爲這將是明智的start a new question而不是混淆這一個。其他人可能會發現這個問題對目前的形式有用。

回答

1

由於用戶沒有在其標準中直接指定結束日期,因此問題比初看起來更簡單。

SELECT * FROM periods p 
WHERE p.range_start >= @min_start 
AND p.range_start <= @max_start 
AND DATE_ADD(p.range_start, INTERVAL @duration DAY) <= p.range_end 
1

這不是SQL的好選擇。

但是,在Django中,您可以從許多SQL約束中解脫出來。

首先,在您的模型中定義一個方法函數,以Python的方式執行您所需的操作。

例如

class MyThing(models.Model): 
    startDate = models.DateField(...) 
    duration = models.IntegerField(...) 
    def isInside(self, aDate, aDuration): 
     return aDate >= self.startDate and aDate+aDuration <= self.startDate+self.duration 

然後用你的isInside()方法資格的對象。這將在Python中完成一些工作,比在SQL中進行簡單得多。

爲這樣的複雜查詢定義自定義管理器。您將擴展基本的query_set方法以包含類似於此的邏輯。

for thing in MyThing.objects.filter(startDate__gte=aDate, startDate__lte=aDate+duration): 
    if thing.isInside(aDate, duration): 
     return thing 

這將使用SQL來獲取對象的子集,其日期應包含您要查找的時間間隔。然後您可以從該列表中選擇最終對象的間隔。

+0

想象一下,我正在一個月內檢查3天。有什麼比運行30個查詢更好嗎? (我會將這一點加入到原始問題中) – 2009-04-22 17:48:33

+0

我一直在跟蹤你,直到你說:'得到一個接近的日期子集,然後從該列表中選擇'。你能澄清嗎? – 2009-04-22 18:10:55

+0

MyThing.objects.filter(startDate__gte = aDate,startDate__lte = aDate + duration)是應包含您要查找的範圍的對象的子集。 – 2009-04-22 18:42:52

0

這個怎麼樣。

創建一個日期表,每個caledar日期一行。

SELECT * FROM CalendarDates cd 
    LEFT JOIN period p 
     ON cd.caldate > p.end_date 
     OR cd.caldate + duration < p.begin_date 

    WHERE p.period_id IS NULL 
1

幽州用戶指定(舉例來說):

  • 1周時間內
  • 開始日期(2009年5月1日)
  • 結束日期(2009年5月15日)


然後您聲明您需要「找出是否有一週插槽在他們指定的範圍內「。我不是100%肯定,如果我理解正確的,但是這是我從那個得到...

  • 沒有「提供週期」(由開始/結束日期描述)
  • 的表您需要在與用戶的開始/結束圈找到一個「avaialble期」釋日期
  • 重疊必須持續至少1周(或任何時間,用戶需要)


如果是這種情況下,我會按如下方式解決......

  • 找出重疊
  • 期間確定第一重疊日期
  • 確定最後的重疊日期
  • 如果這些日期間隔7天,這是一個比賽


我在SQL中的解決方案將...

SELECT 
    * 
FROM 
    periods 
WHERE 
    (range_start <= @check_end) 
    AND (range_end >= @check_start) 
    AND DATEDIFF(
      DAY, 
      CASE WHEN range_start > @check_start THEN range_start ELSE @check_start END, 
      CASE WHEN range_end < @check_end THEN range_end ELSE @check_end END 
     ) 
     >= @required_duration-1 


編輯

這是假設開始和結束日期被包容你的榜樣邏輯暗示。
(2009年1月01日 - >'2009年1月01日')的一天期間)

我個人更喜歡開始日期包含,結束日期獨家。
(爲期一天的週期由「2009年1月01 repesented - >「2009年1月02」)

原因是,各種工科數學比較和操作變得更容易,而且也因爲它不rquire讀者假設你在工作的準確程度。

  • 如果按小時等級「2009年1月1日」 - >「2009年1月1日」工作時間爲1小時。
  • 但'2009年1月01日 - >'2009年1月2日'總是一天,如果你知道結束日期是獨家。
1

在某些情況下,創建一個查詢以獲取您可能需要的所有數據,然後使用業務邏輯語言在測試之前對其進行過濾,結果會更快。

在我正在開發的應用程序中,通過滾動平均值進行類似的操作,可節省超過100倍。