比较两个日期范围时一个范围内有一个范围开始日期
我已经从这个拿到了下一个问题了: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而不是混淆这一个。其他人可能会发现这个问题对目前的形式有用。
由于用户没有在其标准中直接指定结束日期,因此问题比初看起来更简单。
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
这不是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来获取对象的子集,其日期应包含您要查找的时间间隔。然后您可以从该列表中选择最终对象的间隔。
这个怎么样。
创建一个日期表,每个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周时间内
- 开始日期(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日'总是一天,如果你知道结束日期是独家。
在某些情况下,创建一个查询以获取您可能需要的所有数据,然后使用业务逻辑语言在测试之前对其进行过滤,结果会更快。
在我正在开发的应用程序中,通过滚动平均值进行类似的操作,可节省超过100倍。
想象一下,我正在一个月内检查3天。有什么比运行30个查询更好吗? (我会将这一点加入到原始问题中) – 2009-04-22 17:48:33
我一直在跟踪你,直到你说:'得到一个接近的日期子集,然后从该列表中选择'。你能澄清吗? – 2009-04-22 18:10:55
MyThing.objects.filter(startDate__gte = aDate,startDate__lte = aDate + duration)是应包含您要查找的范围的对象的子集。 – 2009-04-22 18:42:52