2012-02-08 6 views
14

Есть ли более эффективный способ сделать следующее?Возврат «последней» строки каждой «группы по» в MySQL

select * 
    from foo as a 
    where a.id = (select max(id) from foo where uid = a.uid group by uid) 
    group by uid; 
) 

Этот ответ похож, но это ответ на лучший способ сделать это - How to select the first row for each group in MySQL?

Спасибо,

Криса.

P.S. таблица выглядит следующим образом:

CREATE TABLE foo (
    id INT(10) NOT NULL AUTO_INCREMENT, 
    uid INT(10) NOT NULL, 
    value VARCHAR(50) NOT NULL, 
    PRIMARY KEY (`id`), 
    INDEX `uid` (`uid`) 
) 

данные:

id, uid, value 
1, 1, hello 
2, 2, cheese 
3, 2, pickle 
4, 1, world 

результаты:

id, uid, value 
3, 2, pickle 
4, 1, world 

См http://www.barricane.com/2012/02/08/mysql-select-last-matching-row.html для более подробной информации.

+0

Это коррелированный подзапрос. Как правило, некоррелированный подзапрос будет работать быстрее, как пример Деварта. – Strawberry

+0

Возможный дубликат [Получение последней записи в каждой группе] (http: // stackoverflow.com/questions/1313120/retrieve-the-last-record-in-each-group) –

ответ

33

Попробуйте этот запрос -

SELECT t1.* FROM foo t1 
    JOIN (SELECT uid, MAX(id) id FROM foo GROUP BY uid) t2 
    ON t1.id = t2.id AND t1.uid = t2.uid; 

Затем используйте EXPLAIN для анализа запросов.


SELECT t1.* FROM foo t1 
    LEFT JOIN foo t2 
    ON t1.id < t2.id AND t1.uid = t2.uid 
WHERE t2.id is NULL; 
+0

Это не работает как представление - я получаю «ERROR 1349 (HY000): SELECT View содержит подзапрос в предложении FROM», тогда как мой код. – fadedbee

+1

Я не знал, что вы собираетесь использовать его для просмотра. ... Я добавил еще один. – Devart

+0

Спасибо, мне нужно будет сделать несколько тестов по всем трем альтернативам и отчитаться. (Мне удалось сделать ваше первое решение для просмотра, сделав подзапрос отдельным видом.) – fadedbee

2

если таблица большого размера. Сделать view, содержащих все строки последнего идентификатор

create view lastrecords as (select max(id) from foo where uid = a.uid group by uid) 

Теперь присоединиться к вашему основному запросу с этим view. Это будет быстрее.

SELECT t1.* FROM tablename as t1 
    JOIN lastrecords as t2 
    ON t1.id = t2.id AND t1.uid = t2.uid; 

ИЛИ Вы можете сделать присоединиться к последней записи прямой в запросе также:

SELECT t1.* FROM tablename as t1 
JOIN (SELECT uid, MAX(id) id FROM tablename GROUP BY id) as t2 
ON t1.id = t2.id AND t1.uid = t2.uid; 
0

Это работало для меня спасибо!

SELECT t1.* FROM foo t1 
    JOIN (SELECT uid, MAX(id) id FROM foo GROUP BY uid) t2 
    ON t1.id = t2.id AND t1.uid = t2.uid; 

моя версия:

SELECT * FROM messages t1 JOIN (SELECT MAX(id) id FROM messages where uid = 8279 and actv=1 GROUP BY uid) t2 ON t1.id = t2.id ORDER BY datex desc LIMIT 0,10; 

этот код ниже не возвращает все строки, которые я хочу, потому что, если столбец не более идентификатор является неактивным один, то он пропускает группу, даже если группа имеет активные строки. .

select * from messages where uid = 8279 and actv=1 and id In (Select max(id) From messages Group By uid) order by datex desc; 
4

Возвращаясь последнюю строку каждого GROUP BY в MySQL с WHERE пункта:

SELECT * 
FROM foo 
WHERE id IN (
    SELECT Max(id) 
    FROM foo 
    WHERE value='XYZ' 
    GROUP BY u_id 
) 
LIMIT 0,30 
1

Самый простой способ: вы можете выбрать из выбранный список, который отсортирован.

SELECT * FROM (SELECT * FROM foo order by id DESC) AS footbl 
group by uid 
order by id DESC