2013-02-27 1 views
0

У меня есть следующие две таблицMYSQL Выбор старейшей записи даты для каждого уникального события

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; 

Где ссылка event_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 

Этот запрос является результатом нескольких попыток дальнейшего улучшения медленного времени, которое первоначально имело (1,5 секунды), когда я хотел использовать групповые и другие подзапросы. Его самый быстрый из них, но учитывая, что есть 1400 записей событий и 10000 записей событий, запрос занимает 400 + мс для обработки, также я запускаю подсчет на основе этого (для поисковых запросов), который занимает много времени, поскольку Что ж. Как ни странно, если исключить условие EventDate в главном, где это предложение, это будет еще выше 1 с +.

Есть ли что-нибудь, что я могу сделать для улучшения этого или другого подхода в структуре таблицы?

+0

Как это выполнить без заказа по условию? –

+0

Без заказа он выполняет намного быстрее, но мне действительно нужно их отсортировать таким образом. – zakel

ответ

0

Просто чтобы прояснить кому-либо еще ... на «#» в MySQL выступает как продолжение комментария и в основном игнорируется в запросе, это не «AND EventDate.Date < '2013-02-27». Тем не менее, похоже, вам нужен список всех событий COMING UP, которых еще не произошло. Я бы начал с простого «прекремента», который просто захватывает все события и минимальную дату, основанную на дате события, которая еще не происходит. Тогда присоединиться к этому результату к другим таблицам, чтобы получить остальную часть полей, которые вы хотите

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 

Вашей таблица имеет избыточный индекс идентификатора события, только под разными названиями. Вызов имени индекса date не означает, что индексируется столбец. Значение (значения) в parens (event_id) - это то, на чем построен индекс.

Итак, я хотел бы изменить создать таблицу ...

KEY `date` (`event_id`, `date`, `start_time`) 

Или вручную создать индекс.

Create index ByEventAndDate on Event_Dates (`event_id`, `date`, `start_time`) 
+0

Я изменил его таким образом, и он определенно работает более чем в два раза быстрее. Тем не менее, для предварительного запроса нужна группа Event_ID, в противном случае она выбрала меня только одну самую низкую дату всех событий – zakel

+0

@zakel, рад, что это сработало, я пересмотрел «группу» в ответ ... извините, я пропустил это, но рад вы легко идентифицировали его. – DRapp

0

Если вы говорите об оптимизации, полезно включить планы выполнения, когда это возможно.

Кстати попробовать это те (если вы не пробовали это уже):

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 
+0

Ваше первое решение очень похоже на DRapp's. К сожалению, второй не будет работать, потому что дата может быть меньше для более высокого идентификатора. – zakel

Смежные вопросы