当一个范围具有一系列开始日期时,比较两个日期范围

时间:2009-04-22 17:33:05

标签: sql mysql django date

我从这个问题中得到了下一个问题:Comparing date ranges

比较两个范围的解决方案是查询:

SELECT *   从期间   哪里没有(range_start> @check_period_end            OR range_end< @check_period_start)

我有更多问题。我允许人们进入一系列时期。确切地说,他们输入一个持续时间(即1周)和一系列开始日期(即5月的前2周),我必须找出他们指定的范围内是否有一周的时段。

天真的解决方案是在我的范围内每天运行上述查询。所以 - 要检查一个月范围内的3天时段,我必须运行30个查询。有更有效的方法吗?

奖励积分 - 我正在使用Django。使用Django ORM有一个很好的解决方案吗?

编辑 - 为了简化问题,我想我已经把它变成了另一个问题!我的实际问题是找到“自由空白”。我认为这会使下面的一些“纯SQL”方法无效。我认为start a new question是明智的,而不是混淆这个。其他人可能会发现这个问题在目前的形式中是有用的。

5 个答案:

答案 0 :(得分: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来获取对象的子集,其中日期应包含您要查找的间隔。然后,您可以从该列表中选择最终对象的间隔。

答案 1 :(得分: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

答案 2 :(得分:1)

您声明用户指定(举例):

  • 1周时间
  • 开始日期(2009年5月1日)
  • 结束日期(2009年5月15日)


然后,您声明需要“查明他们指定的范围内是否有一周的插槽”。如果我理解正确的话,我不是100%肯定,但这就是我从中得到的......

  • 有一个“可用期间”表(由开始/结束日期描述)
  • 您需要在用户的开始/结束日期的圈数中找到一个“avaialble period”。
  • 重叠必须持续至少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月1日' - &gt;'2009年1月1日'重播的一天期间)

我个人更喜欢开始日期包含,结束日期独家 (“2009年1月1日” - &gt;“2009年1月2日”重播了一天的时间段)

原因是各种数学比较和操作变得更容易,但也因为它并不要求读者假设你正在使用的准确度。

  • 如果按小时工作'2009年1月1日' - > '2009 Jan 01'代表一小时。
  • 但'2009 Jan 01' - &gt;如果你知道结束日期是独家的,'2009年1月02'总是一天。

答案 3 :(得分:1)

在某些情况下,创建一个获取您可能需要的所有数据的查询的速度要快几个数量级,然后在测试之前使用业务逻辑语言对这些数据进行过滤。

在我正在处理的应用程序中使用滚动平均值执行与此类似的操作时,节省了超过100倍。

答案 4 :(得分:0)

这个怎么样。

创建一个日期表,每个日历日期一行。