Mysql запрос головоломки - поиск того, что было бы самой последней датой

StackOverflow https://stackoverflow.com/questions/2837441

Вопрос

Я посмотрел все и еще не нашел интеллектуальный способ справиться с этим, хотя я уверен, что можно:

Одна таблица исторических данных имеет ежеквартальную информацию:

CREATE TABLE Quarterly (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
PRIMARY KEY (unique_ID));

Еще одна таблица исторических данных (которая очень большая) содержит ежедневная информация:

CREATE TABLE Daily (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
qtr_ID INT UNSIGNED,
PRIMARY KEY (unique_ID));

Поле QTR_ID не является частью подачи ежедневных данных, которые населены базы данных - вместо этого мне нужно обратное обратное заполнение поля Qtr_id в ежедневной таблице с quartlyly.unique_id id ряд ряд, используя, как было бы самые последние ежеквартальные данные что daily.date_posted для этого источника данных.

Например, если ежеквартальные данные

101 2009-03-31 1 4.5
102 2009-06-30 1 4.4
103 2009-03-31 2 7.6
104 2009-06-30 2 7.7
105 2009-09-30 1 4.7

и ежедневные данные

1001 2009-07-14 1 3.5 ??
1002 2009-07-15 1 3.4 &&
1003 2009-07-14 2 2.3 ^^

Тогда мы хотели бы ?? Поле Qtr_id должно быть назначено «102» как последний квартал для этого источника данных в этой дате, и && также будет «102», а ^^ будет «104».

Проблемы включают в себя, что обе таблицы (особенно ежедневные таблицы) на самом деле очень велики, их нельзя нормализовать, чтобы избавиться от повторяющихся дат или иным образом оптимизированных, и для определенных ежедневных записей нет предшествующих квартальной записи.

Я пробовал множество присоединений, используя Dateiff (где вызов находит минимальное значение Dateiff, больше нуля), а для меня другие попытки, но ничего не работает - обычно мой синтаксис где-то ломается где-то. Любые идеи приветствуют - я выполню любые основные идеи или концепции и доклад.

Это было полезно?

Решение

Просто подзапрос на ID четверти, используя что-то вроде:

(
 SELECT unique_ID 
 FROM Quarterly 
 WHERE 
     datasource = ? 
     AND date_posted >= ? 
 ORDER BY
     unique_ID ASC
 LIMIT 1
)

Конечно, это, вероятно, не даст вам наилучшую производительность, и она предполагает, что даты добавляются в квартал последовательно (в противном случае order by date_posted). Тем не менее, это должно решить вашу проблему.

Вы бы использовали этот подзапрос на вашем INSERT или UPDATE заявления как стоимость вашего qtr_ID поле для вашего Daily стол.

Другие советы

Следующее, по-видимому, работает точно так же, как предназначено, но это, безусловно, является уродливым (с тремя вызовами к одному и тому же Dateiff !!), возможно, увидев рабочий запрос, кто-то может быть в состоянии дальше уменьшить его или улучшить:

UPDATE Daily SET qtr_ID = (select unique_ID from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) = 
(SELECT MIN(DATEDIFF(Daily.date_posted, Quarterly.date_posted)) from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) > 0));

После получения дополнительной работы над этим запросом я оказался огромным улучшением производительности над оригинальной концепцией. Наиболее важным улучшением было создание индексов как в ежедневных, так и ежеквартальных таблицах - в ежедневной основе я создал индексы (DataSource, Date_Posted) и (DataSource, DataSource), используя BTREE и ON (DataSource), используя хеш, а в квартал я сделал то же самое предмет. Это излишки, но он убедился, что у меня был вариант, который может использовать двигатель запроса. Это уменьшило время запроса до менее чем 1% от того, что было. (!!)

Затем я узнал, что учитывая мои особые обстоятельства, которые я мог бы использовать Max () вместо порядка и ограничить, поэтому я использую вызов на MAX (), чтобы получить соответствующий Unique_id. Это уменьшило время запроса примерно на 20%.

Наконец, я узнал, что с механизмом хранения InnoDB я мог бы сегментировать кусок ежедневного стола, который я обновил с любым запросом, который позволил мне многорезать запросы с небольшим количеством локтя и сценариев. Параллельная обработка работала хорошо, и каждая нить снизила время линейно.

Итак, основной запрос, который выполняет буквально в 1000 раз лучше, чем моя первая попытка:

UPDATE Daily
SET qtr_ID =
(
  SELECT MAX(unique_ID)
  FROM Quarterly
  WHERE Daily.datasource = Quarterly.datasource AND
        Daily.date_posted > Quarterly.dateposted
)
WHERE unique_ID > ScriptVarLowerBound AND
      unique_ID <= ScriptVarHigherBound
;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top