Это не так просто, как одиночное внешнее соединение с левой таблицей, потому что вы хотите, чтобы пустые значения, оставленные внешним соединением, были заполнены самой последней ценой.
EXPLAIN SELECT v.`date`, v.volume_amt, p1.item_id, p1.price
FROM Volume v JOIN Price p1
ON (v.`date` >= p1.`date` AND v.item_id = p1.item_id)
LEFT OUTER JOIN Price p2
ON (v.`date` >= p2.`date` AND v.item_id = p2.item_id
AND p1.`date` < p2.`date`)
WHERE p2.item_id IS NULL;
Этот запрос сопоставляет Volume со всеми строками в Price, которые были ранее, а затем использует другое соединение, чтобы убедиться, что мы находим только самую последнюю цену.
Я проверял это на MySQL 5.0.51. Он не использует ни коррелированных подзапросов, ни группировать по.
edit: Обновлен запрос для соответствия item_id и дате. Кажется, это тоже работает. Я создал индекс на (date)
и индекс на (date, item_id)
, и план EXPLAIN был идентичен. Индекс на (item_id, date)
может быть лучше в этом случае. Вот вывод EXPLAIN для этого:
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+
| 1 | SIMPLE | p1 | ALL | item_id | NULL | NULL | NULL | 6 | |
| 1 | SIMPLE | v | ref | item_id | item_id | 22 | test.p1.item_id | 3 | Using where |
| 1 | SIMPLE | p2 | ref | item_id | item_id | 22 | test.v.item_id | 1 | Using where; Using index; Not exists |
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+
Но у меня очень маленький набор данных, и оптимизация может зависеть от больших наборов данных. Вы должны экспериментировать, анализируя оптимизацию, используя больший набор данных.
edit: Я вставил неправильный вывод EXPLAIN раньше. Вышеуказанное исправлено и показывает лучшее использование индекса (item_id, date)
.