日期范围搜索

时间:2015-05-12 20:58:35

标签: mysql performance date-range

Quassnoi和其他人已经发布了一些相关的解决方案,但他们并不适用于这种特殊情况。

在MySql表中有大约200万条记录, (Id int,StartDate date,EndDate date)和一些信息。 我需要隔离触及特定日期范围的记录(From-To)示例:哪些记录触及11月份

SELECT id 
    FROM Records
    WHERE StartDate<="2015-11-30"
      AND EndDate>="2015-11-01"

开始日期和结束日期之间的差异通常很小,但可能很大(超过一年)。这就是Quassnoi以前的答案不起作用的原因。 我不能让它在适当的时间运行。

任何帮助/建议都将不胜感激。

2 个答案:

答案 0 :(得分:0)

这是一个难题。否INDEX将运作良好。

但是,让我勾勒出一个涉及额外表格和一些额外处理的解决方法。

  1. 选择一个时间段,例如'月'(与您的示例一样)。
  2. 构建另一个包含PRIMARY KEY(月,id)的表,其中id是预订的ID。 (我认为不需要任何其他专栏。)
  3. 对于每条记录(在当前表格中),使用预订id以及部分或全部跨越的月份,使用一行或多行填充新表格。
  4. “哪些预订在11月使用房间”应该非常简单明了。
  5. “4月28日至5月4日期间使用哪些预订房间需要查看4月和5月的ID,然后检查实际的开始/结束日期以过滤掉那些不适用的日期。
  6. 如果使用'周'(而不是'月'),新表中会有更多行,但选择性更好 - 从长远来看很难说哪个更好。

    因此,查询变为如下所示。 (我假设$ start_date $ $ end_date是DATE并且包含。)

    SELECT ...
        FROM new_table AS n
        JOIN bookings AS b USING(id)
        WHERE start_date <= n.month + INTERVAL 1 MONTH
          AND n.month <= $end_date
          AND ... same stuff for b. ...
    

答案 1 :(得分:0)

此测试在:php 5.4 / MySql 5.5.42中执行 双SSD Raid-1。

表预订,有近200万条记录和周数(超过200万条记录,因为有些预订超过2周或更长时间)

CREATE TABLE `bookings` (
  `id` int(11) NOT NULL AUTO_INCREMENT, ## id is booking number.
  `start_date` date DEFAULT NULL,
  `end_date` date DEFAULT NULL,
  /* .  . . . . .  Rest of booking's info */
  PRIMARY KEY (`Id`),
  KEY `st_end` (`start_date, end_date`),
  KEY `end_date` (`end_date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8  COMMENT='A record for each booking';


 CREATE TABLE `weeks` (
   `Id` int(11) NOT NULL AUTO_INCREMENT,
   `bk_nr` int(11) DEFAULT NULL,
   `week` int(11) DEFAULT NULL,
   PRIMARY KEY (`Id`),
   KEY `week` (`week`),
   KEY `bk_nr` (`bk_nr`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 
 COMMENT='Records indicate that booking (bk_nr) touches week number (week)';

每个预订可能在&#34;周&#34;中有几个记录。每周一次,它接触到。

使用日期(&#34; oW&#34;)在php中生成周。它创建了一周,例如:2015-03-01:201509(2015年第09周)。

测试结果。搜索使用2015年3月的任何一天的预订。 最糟糕的是。

0,56秒 SELECT DISTINCT c.* FROM bookings c WHERE c.d_start_date <= "2015-03-31" AND c.d_end_date >= "2015-03-01" AND c.id in ( SELECT w.bk_nr FROM weeks w
WHERE w.week between 201509 AND 201514 );

0,14秒 SELECT DISTINCT c.* FROM bookings c, weeks w WHERE c.id = w.bk_nr AND w.week between 201509 AND 201514 AND c.d_start_date <= "2015-03-31" AND c.d_end_date >= "2015-03-01";

获胜者是。 。 。

最佳:0,1秒 SELECT DISTINCT * FROM bookings WHERE start_date <= "2015-03-31" AND end_date >= "2015-03-01";

看起来MySql已经从之前的测试中改进了(在mysql 4.x中执行),现在它知道如何有效地处理这种类型的查询。

无需帮助。 (在每次查询之前和之后,简单地用&#34; SELECT now()&#34;来衡量时间。) 谢谢Rick James的帮助。