помогите оптимизировать запрос

soullibra

Новичок
помогите оптимизировать запрос

есть таблица с полями id, station, date, <всякие данные>
нужно из таблицы выбрать все station за последнюю дату (у каждой station последняя дата разная) ну и соответствующие им (<station,date>) данные.
пока придумал так:
Код:
SELECT r.*
FROM
	(SELECT MAX(date) AS mdate, station FROM rad WHERE 1=1 GROUP BY station) AS t,
	rad AS r
WHERE
	t.station = r.station AND t.mdate = r.date;
время выполнения 15.47 сек, что не есть гуд
возможно ли написать более опримизированно? если да, то посоветуйте как.
 

Gas

может по одной?
убери во вложенном запросе получение `station` и группировку, джойнь только по дате. На `date` индекс должен стоять.
Explain запроса тоже покажи.
 

zerkms

TDD infected
Команда форума
[sql]
SELECT * FROM `rad` `o` WHERE `o`.`date` = (SELECT MAX(`date`) FROM `rad` `i` WHERE `i`.`station` = `o`.`station`)
[/sql]

индекс нужен - составной (station + date)
 

Wicked

Новичок
zerkms
это же correlated subquery будет, не?
а про индекс согласен
 

soullibra

Новичок
возможно я плохо написал что нужно получить в результате... возможно не понял Вашего предложения...
например, есть таблица:
Код:
mysql> select * from test;
+----+---------+------------+
| id | station | date       |
+----+---------+------------+
|  1 |       1 | 2010-01-01 | 
|  2 |       2 | 2010-01-02 | 
|  3 |       3 | 2010-01-03 | 
|  4 |       1 | 2010-01-03 | 
|  5 |       2 | 2010-01-04 | 
+----+---------+------------+
5 rows in set (0.00 sec)
ожидаемый результат выборки
Код:
mysql> select w.* from (select max(date) as mdate, station from test where 1=1 group by station) as t, test as w where t.station=w.station and t.mdate=w.date;
+----+---------+------------+
| id | station | date       |
+----+---------+------------+
|  3 |       3 | 2010-01-03 | 
|  4 |       1 | 2010-01-03 | 
|  5 |       2 | 2010-01-04 | 
+----+---------+------------+
3 rows in set (0.03 sec)
предложеный вариант
Код:
mysql> select w.* from (select max(date) as mdate from test where 1=1) as t, test as w where t.mdate=w.date;
+----+---------+------------+
| id | station | date       |
+----+---------+------------+
|  5 |       2 | 2010-01-04 | 
+----+---------+------------+
1 row in set (0.00 sec)
в предложеных вариантах, я не понял зачем убирать station во вложенном запросе

PS: про индекс я понял... ща буду раазбираться... база просто уже готовая и забитая
Код:
mysql> select count(id) from rad;
+-----------+
| count(id) |
+-----------+
|   3883354 | 
+-----------+
-~{}~ 06.05.10 18:47:

протупил... этот вариант действительно работает, но медленнее.
Автор оригинала: zerkms
[sql]
SELECT * FROM `rad` `o` WHERE `o`.`date` = (SELECT MAX(`date`) FROM `rad` `i` WHERE `i`.`station` = `o`.`station`)
[/sql]

индекс нужен - составной (station + date)
он конечно более красив :) возможно с группой индексов он работает быстрее... буду тестить. спасибо.
 

Gas

может по одной?
я не понял зачем убирать station во вложенном запросе
лично я проглядел что
(у каждой station последняя дата разная)
soullibra
твой запрос в первом посте должен неплохо работать с уже предложенным составным индексом (station + date).
В любом случае, в следующих сообщениях приводи explain'ы запросов.
 

zerkms

TDD infected
Команда форума
это же correlated subquery будет, не?
будет, а что поделаешь :)

разве что
WHERE (station, date) IN (SELECT `station`, MAX(`date`) FROM `rad` GROUP BY `station`)

можно так пробовать, но я хз как такая штука оптимизируется

ps: вот только я не уверен, что это синтаксически корректно
 

prolis

Новичок
Зачастую max(date) соответвует записи с max(id), тогда можно с использованием праймэри кея:
[sql]SELECT r.*
FROM
(SELECT MAX(id) AS id FROM rad WHERE 1=1 GROUP BY station) AS t,
rad AS r
WHERE
t.id = r.id[/sql]
 

zerkms

TDD infected
Команда форума
Wicked
зависит от ситуации :) недавно же на mysqlperformance был пример, когда связанный подзапрос был сильно быстрее :)
 
Сверху