0

我有一张桌子,每一行都有一个start_dateend_dateend_date可以在与开始日期不同的年份。

我需要选择与输入月份范围重叠的所有记录。

例如:

n  start_date  end_date  
1  2010-12-03  2010-03-29  // months are 12,1,2,3  
2  2012-03-11  2010-06-24  // months are 3,4,5,6  
3  2010-06-17  2010-10-04  // months are 6,7,8,9,10  
4  2010-07-03  2010-09-21  // months are 7,8,9  
5  2010-04-21  2011-05-13  // months are 1..12 

输入范围为 3、4、5、6。输出行应为:1,2,3,5。只有第 4 行在任何月份都没有重叠。

如何在 SQlite/MySQL 中执行此操作?

我正在使用 Ruby on Rails。

4

3 回答 3

1

“输入范围”听起来像是一个连接范围。因此,如果没有 12 个月的范围,典型的解决方案将是where month(start_date) <= $end_month and month(end_date) >= $start_month.

但是这样我们就需要模数的整个范围。我会将关系推广到 1..24 个月。

这意味着范围是:

month(start_date) ... month(end_date) + 12*(year(end_date) - year(start_date))

现在$from, $to必须推出给定的范围:

if($to < $from){ 
    $to += 12;
}

并且关系推广到

month(start_date) <= $to 
and (month(end_date) + 12*(year(end_date) - year(start_date))) >= $from

希望有帮助。

于 2013-05-25T19:06:35.100 回答
0

像这样的事情应该在一条 SQL 中完成:-

SELECT DISTINCT n
FROM SomeTable,
(SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 10 UNION SELECT 11) a
WHERE DATE_ADD(DATE_SUB(SomeTable.start_date, INTERVAL DAYOFMONTH(SomeTable.start_date)-1 DAY), INTERVAL a.i MONTH) <= SomeTable.end_date
AND MONTH(DATE_ADD(DATE_SUB(SomeTable.start_date, INTERVAL DAYOFMONTH(SomeTable.start_date)-1 DAY), INTERVAL a.i MONTH)) IN (3, 4, 5, 6)

只要结果日期小于或等于该行的结束日期,这将最多添加 11 个月到每个开始日期。这可能会为每个初始行提供 12 个结果行,在该范围内每个月一个,并使用 IN 子句针对您要检查的月份进行检查。

在括号中使用 DATE_SUB 的奇怪做法是使用该月的第一天。否则,将一个月添加到 2013:02:28 会得到一个大于 2013:03:01 的日期,因此如果没有这个游戏,你只会得到 2 月而不是 3 月。

于 2013-05-25T19:19:37.657 回答
0

SomeClass.where("start_date >= ? end_date <= ?", start_date.beginning_of_month, end_date.end_of_month)

于 2013-05-25T20:49:24.157 回答