MYSQL为每个唯一事件选择最早的日期记录
我有下面两张桌子MYSQL为每个唯一事件选择最早的日期记录,mysql,database,optimization,Mysql,Database,Optimization,我有下面两张桌子 CREATE TABLE IF NOT EXISTS `events` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM; CREATE TABLE IF NOT EXISTS `events_dates` ( `id` bigint(20) NOT NULL AUTO_INCREMENT,
CREATE TABLE IF NOT EXISTS `events` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
CREATE TABLE IF NOT EXISTS `events_dates` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`event_id` bigint(20) NOT NULL,
`date` date NOT NULL,
`start_time` time NOT NULL,
`end_time` time NOT NULL,
PRIMARY KEY (`id`),
KEY `event_id` (`event_id`),
KEY `date` (`event_id`)
) ENGINE=MyISAM;
其中链接是事件\ u id
我想要的是检索所有唯一的事件记录,它们各自的事件日期按一定时间段内最小的升序日期排序
基本上,下面的查询正是我想要的
SELECT Event.id, Event.title, EventDate.date, EventDate.start_time, EventDate.end_time
FROM
events AS Event
JOIN
com_events_dates AS EventDate
ON (Event.id = EventDate.event_id AND EventDate.date = (
SELECT MIN(MinEventDate.date) FROM events_dates AS MinEventDate
WHERE MinEventDate.event_id = Event.id AND MinEventDate.date >= CURDATE() # AND `MinEventDate`.`date` < '2013-02-27'
)
)
WHERE
EventDate.date >= CURDATE() # AND `EventDate`.`date` < '2013-02-27'
ORDER BY EventDate.date ASC , EventDate.start_time ASC , EventDate.end_time DESC
LIMIT 20
这个查询是多次尝试进一步改进缓慢时间的结果。当我想要使用group by和其他子查询时,最初只有1.5秒。这是迄今为止速度最快的一个,但考虑到总共有1400个事件记录和10000个事件记录,查询需要400毫秒以上的时间来处理,我也基于此运行了一个计数,以便进行分页,这也需要很多时间。
奇怪的是,在主where子句中省略EventDate条件会导致更高的1s+
我能做些什么来改进表结构的这种或不同的方法吗?如果您谈论的是优化,那么在可能的情况下包括执行计划会很有帮助 顺便说一句,如果您还没有尝试过,请尝试以下方法:
SELECT
Event.id,
Event.title,
EventDate.date,
EventDate.start_time,
EventDate.end_time
FROM
(select e.id, e.title, min(date) as MinDate
from events_dates as ed
join events as e on e.id = ed.event_id
where date >= CURDATE() and date < '2013-02-27'
group by e.id, e.title) as Event
JOIN events_dates AS EventDate ON Event.id = EventDate.event_id
and Event.MinDate = EventDate.date
ORDER BY EventDate.date ASC , EventDate.start_time ASC , EventDate.end_time DESC
LIMIT 20
;
#assuming event_dates.date for greater event_dates.id always greater
SELECT
Event.id,
Event.title,
EventDate.date,
EventDate.start_time,
EventDate.end_time
FROM
(select e.id, e.title, min(ed.id) as MinID
from events_dates as ed
join events as e on e.id = ed.event_id
where date >= CURDATE() and date < '2013-02-27'
group by e.id, e.title) as Event
JOIN events_dates AS EventDate ON Event.id = EventDate.event_id
and Event.MinID = EventDate.id
ORDER BY EventDate.date ASC , EventDate.start_time ASC , EventDate.end_time DESC
LIMIT 20
只是为了向其他人澄清。。。MySQL中的注释作为延续注释,在查询中基本上被忽略,它不是和EventDate.Date<'2013-02-27'。这就是说,您似乎想要一份尚未发生的所有事件的列表。我将从一个简单的预查询开始,它只获取所有事件以及基于尚未发生的事件日期的最小日期。然后将该结果连接到其他表,以获得所需的其余字段
SELECT
E.ID,
E.Title,
ED2.`date`,
ED2.Start_Time,
ED2.End_Time
FROM
( SELECT
ED.Event_ID,
MIN( ED.`date` ) as MinEventDate
from
Event_Dates ED
where
ED.`date` >= curdate()
group by
ED.Event_ID ) PreQuery
JOIN Events E
ON PreQuery.Event_ID = E.ID
JOIN Event_Dates ED2
ON PreQuery.Event_ID = ED2.Event_ID
AND PreQuery.MinEventDate = ED2.`date`
ORDER BY
ED2.`date`,
ED2.Start_Time,
ED2.End_Time DESC
LIMIT 20
您的表在事件ID上有冗余索引,只是名称不同而已。调用索引日期的名称并不意味着该列正在被索引。parens event_id中的值是建立索引的基础
所以,我想将您的创建表更改为
KEY `date` ( `event_id`, `date`, `start_time` )
或者,手动创建索引
Create index ByEventAndDate on Event_Dates ( `event_id`, `date`, `start_time` )
如果没有ORDERBY子句,它的性能如何?如果没有ORDERBY,它的性能会快得多,但我真的需要它们按这种方式排序。我对它进行了这样的调整,它的运行速度肯定是原来的两倍多。但是,预查询需要按事件\u ID分组,否则它只选择所有事件中最低的一个日期events@zakel,很高兴它成功了,我修改了答案中的“分组依据”。。。很抱歉我错过了它,但很高兴您很容易识别它。您的第一个解决方案与DRapp的非常相似。不幸的是,第二种方法行不通,因为对于更高的id,日期可能更小。