2010-08-08 1 views
2

У меня есть одна таблица с некоторыми данными, и я хочу выбрать новые данные для каждого типа ...MySQL Query, Subquery оптимизация, SELECT, JOIN

Таблица:

+----+------+------+---------------------+ 
| ID | data | type | date    | 
+----+------+------+---------------------+ 
| 1 | just | 2 | 2010-08-07 14:24:48 | 
| 2 | some | 2 | 2010-08-07 18:07:32 | 
| 3 | data | 9 | 2010-08-06 02:52:17 | 
| 4 | abcd | 1 | 2010-08-08 17:23:22 | 
| 5 | efg1 | 5 | 2010-07-10 21:36:55 | 
| 6 | c123 | 5 | 2010-07-10 20:44:36 | 
| 7 | bbey | 12 | 2010-08-09 09:01:26 | 
+----+------+------+---------------------+ 

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

SELECT `data`,`type`,`date` 
FROM `table1` 
WHERE `date` = (
        SELECT MAX(`date`) 
        FROM `table1` AS tbl2 
        WHERE tbl2.`type` = `table1`.`type` 
       ) 
GROUP BY `type` 
ORDER BY `type`,`date` 

Результат:

+------+------+---------------------+ 
| data | type | date    | 
+------+------+---------------------+ 
| abcd | 1 | 2010-08-08 17:23:22 | 
| some | 2 | 2010-08-07 18:07:32 | 
| efg1 | 5 | 2010-07-10 21:36:55 | 
| data | 9 | 2010-08-06 02:52:17 | 
| bbey | 12 | 2010-08-09 09:01:26 | 
+------+------+---------------------+ 

Мой вопрос в том, есть ли лучший способ сделать это, некоторые оптимизации, улучшения или, возможно, можно сделать присоединиться?

ответ

2

Вы используете коррелированный подзапрос. Подзапрос зависит от внешнего запроса, и поэтому он должен выполняться один раз для каждой строки внешнего запроса.

В целом это можно улучшить, используя вместо этого ваш подзапрос в качестве производной таблицы. Так как подзапрос в качестве производной таблицы не коррелирует с внешним запросом, это решение считается более масштабируемой:

SELECT t1.`data`, t1.`type`, t1.`date` 
FROM  `table1` t1 
JOIN  (
       SELECT MAX(`date`) `max_date`, `type` 
       FROM  `table1` 
       GROUP BY `type` 
     ) der_t ON (der_t.`max_date` = t1.`date` AND der_t.`type` = t1.`type`) 
GROUP BY t1.`type` 
ORDER BY t1.`type`, t1.`date`; 

Тестовый случай:

CREATE TABLE table1 (id int, data varchar(10), type int, date datetime); 

INSERT INTO table1 VALUES (1, 'just', 2, '2010-08-07 14:24:48'); 
INSERT INTO table1 VALUES (2, 'some', 2, '2010-08-07 18:07:32'); 
INSERT INTO table1 VALUES (3, 'data', 9, '2010-08-06 02:52:17'); 
INSERT INTO table1 VALUES (4, 'abcd', 1, '2010-08-08 17:23:22'); 
INSERT INTO table1 VALUES (5, 'efg1', 5, '2010-07-10 21:36:55'); 
INSERT INTO table1 VALUES (6, 'c123', 5, '2010-07-10 20:44:36'); 
INSERT INTO table1 VALUES (7, 'bbey', 12, '2010-08-09 09:01:26'); 

Результат:

+------+------+---------------------+ 
| data | type | date    | 
+------+------+---------------------+ 
| abcd | 1 | 2010-08-08 17:23:22 | 
| some | 2 | 2010-08-07 18:07:32 | 
| efg1 | 5 | 2010-07-10 21:36:55 | 
| data | 9 | 2010-08-06 02:52:17 | 
| bbey | 12 | 2010-08-09 09:01:26 | 
+------+------+---------------------+ 
5 rows in set (0.00 sec) 

Оно также похоже, что вы можете вообще избежать подзапросов, используя такое решение, как следующее:

SELECT  t1.`data`, t1.`type`, t1.`date` 
FROM  `table1` t1 
LEFT JOIN `table1` t2 ON (t1.`date` < t2.`date` AND t1.`type` = t2.`type`) 
WHERE  t2.`date` IS NULL 
GROUP BY t1.`type` 
ORDER BY t1.`type`, t1.`date`; 

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