2009-11-22 6 views
0

У меня есть таблицаПоиск ближайших данных?

CREATE TABLE `symbol_details` (
    `symbol_header_id` int(11) DEFAULT NULL, 
    `DATE` datetime DEFAULT NULL, 
    `ADJ_NAV` double DEFAULT NULL 
) 

с ~ 20000000 записей. Теперь я хочу, чтобы найти значение ADJ_NAV ближе к концу квартала только для одного symbol_header_id:

SET @quarterend = '2009-3-31'; 

SELECT symbol_header_id AS she, ADJ_NAV AS aend FROM symbol_details 
WHERE 
symbol_header_id = 18546 
AND DATE= (
# date closest after quarter end 
SELECT DATE FROM symbol_details 
WHERE ABS(DATEDIFF(DATE, @quarterend)) < 10 
AND DATE<[email protected] 
AND symbol_header_id = 18546 
ORDER BY ABS(DATEDIFF(DATE, @quarterend)) ASC LIMIT 1) 

Когда я бегу внутренний «выберите дату» запрос возвращается быстро. Просто запуск внешнего запроса с нужной датой, заполненной вместо подзапроса, также заканчивается очень быстро. Но когда я управляю всем этим, это берет навсегда - что-то не так?

+0

У вас есть индекс по дате, а также symbol_header_id? – Donnie

+0

я. Один на дату и один на symbol_header_id и дата плюс один на symbol_header_id. Отмечено ли это так, как оценивается запрос? –

ответ

1

Возможно, вы можете обойтись без подзапроса. Просто возьмите первый ряд:

SELECT * 
FROM symbol_details 
WHERE DATE <= @quarterend 
AND symbol_header_id = 18546 
ORDER BY DATE DESC 
LIMIT 1 
+0

Это правда, но тогда проблема в том, что если нет данных для этого квартала, они вернут действительно старые данные. Но я мог бы просто добавить И дата> @квартальный старт ... Позвольте мне попробовать. Большое спасибо за ответ! –

+0

Это здорово и привлекло меня к решению, см. Мою речь в текущем оригинальном посте, но мне пришлось изменить это на группу, чтобы получить все значения. Но теперь есть еще одна проблема ... –

+0

@Martin Stein: Я даже не уверен, что такое 'GROUP BY symbol_header_id DESC', поэтому я бы спросил, что в новом вопросе – Andomar

2

Похоже, что у оптимизатора есть некоторые проблемы, чтобы правильно оценить утверждение и найти наиболее эффективный план. (В Oracle я бы попросил вас обновить статистику, но я не уверен, как оптимизатор работает в MySQL.)

Я бы попробовал другие способы выражения вашего заявления, чтобы узнать, что имеет смысл оптимизатор:

  • явно соединить два symbol_header_ids на Имеру и внешнего запроса
  • попробовать SELECT max(date) .. вместо «Order By Limit 1»
  • попробовать сделать само объединение symbol_details

Надеюсь, здесь есть полезная идея.

1

Try:

SELECT t.symbol_header_id, 
      COALESCE(t.adj_nav, '0.0') 'adj_nav' 
    FROM SYMBOL_DETAILS t 
LEFT JOIN (SELECT sh.symbol_header_id, 
        MAX(sh.date) 'max_date' 
      FROM SYMBOL_DETAILS sh 
      WHERE ABS(DATEDIFF(sh.date, @quarter_end)) < 10 
       AND sh.date <= @quarter_end) x ON x.symbol_header_id = t.symbol_header_id 
              AND x.max_date = t.date 
    WHERE t.symbol_header_id = 18546 
Смежные вопросы