对于我正在进行的项目,我有一个包含两个日期的表,这意味着一系列日期,我需要一种方法来在两个日期之间每天“乘以”我的行。
所以例如我开始2017-07-10,结束2017-07-14 2017-07-10,2017-07-11,2017-07-12,2017-07-13我需要有4条线路
为了做到这一点,我发现这里有人提到使用“日历表”,其中包含多年的所有日期。
所以我建造它,现在我有这两个简单的表:
CREATE TABLE `time_sample` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start` varchar(16) DEFAULT NULL,
`end` varchar(16) DEFAULT NULL,
PRIMARY KEY (`societa_id`),
KEY `start_idx` (`start`),
KEY `end_idx` (`end`)
) ENGINE=MyISAM AUTO_INCREMENT=222 DEFAULT CHARSET=latin1;
此表包含我的日期范围,开始和结束都已建立索引,主键是增量int。 样本行:
id start end
1 2015-05-13 2015-05-18
第二张表:
CREATE TABLE `time_dimension` (
`id` int(11) NOT NULL,
`db_date` date NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `td_dbdate_idx` (`db_date`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
对于未来许多年的每一天都有一个索引日期。 样本行:
id db_date
20120101 2012-01-01
现在,我加入了联盟:
select * from time_sample s join time_dimension t on (t.db_date >= start and t.db_date < end);
这需要3毫秒。即使我的第一张桌子是巨大的,这个查询也会非常快(我看到的最多是50毫秒,有很多记录)。
我遇到的问题是在分组结果时(我需要将它们分组为我的应用程序):
select * from time_sample s join time_dimension t on (t.db_date >= start and t.db_date < end) group by db_date;
这需要一秒多的时间,第一个表中没有那么多行,而且显着增加。为什么会发生这种情况?我该如何避免这种情况?
更改数据类型没有用,让第二个表只有一列没有帮助。
我可以提出建议吗:(
答案 0 :(得分:0)
我无法复制这个结果......
我有一个包含大量日期的日历表:calendar(dt)其中dt是PRIMARY KEY DATE数据类型。
$refs
即使有了GROUP BY,我也很难重现这个问题。这是一个简单的COUNT ...
DROP TABLE IF EXISTS time_sample;
CREATE TABLE time_sample (
id int(11) NOT NULL AUTO_INCREMENT,
start date not NULL,
end date null,
PRIMARY KEY (id),
KEY (start,end)
);
INSERT INTO time_sample (start,end) VALUES ('2010-03-13','2010-05-09);
SELECT *
FROM calendar x
JOIN time_sample y
ON x.dt BETWEEN y.start AND y.end;
+------------+----+------------+------------+
| dt | id | start | end |
+------------+----+------------+------------+
| 2010-03-13 | 1 | 2010-03-13 | 2010-05-09 |
| 2010-03-14 | 1 | 2010-03-13 | 2010-05-09 |
| 2010-03-15 | 1 | 2010-03-13 | 2010-05-09 |
| 2010-03-16 | 1 | 2010-03-13 | 2010-05-09 |
...
| 2010-05-09 | 1 | 2010-03-13 | 2010-05-09 |
+------------+----+------------+------------+
58 rows in set (0.10 sec)
EXPLAIN
SELECT * FROM calendar x JOIN time_sample y ON x.dt BETWEEN y.start AND y.end;
+----+-------------+-------+--------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+------+------+--------------------------+
| 1 | SIMPLE | y | system | start | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | x | range | PRIMARY | PRIMARY | 3 | NULL | 57 | Using where; Using index |
+----+-------------+-------+--------+---------------+---------+---------+------+------+--------------------------+
2 rows in set (0.00 sec)