我有一张表格,每行有一个start_date
和end_date
。 end_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。
答案 0 :(得分: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
希望有所帮助。
答案 1 :(得分: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月。
答案 2 :(得分:0)
SomeClass.where("start_date >= ? end_date <= ?", start_date.beginning_of_month, end_date.end_of_month)