2010-04-17 2 views
1

Можно создать дубликат:
Retrieving the last record in each groupЛучший способ построить этот запрос?

Я две таблицы настройки похожи на это (упрощенно для квеста):

Действия-

id - user_id - action - time 

пользователей -

id - name 

Я хочу вывести последнее действие для каждого пользователя. Я понятия не имею, как это сделать.

Я не очень разбираюсь в SQL, но из того, что я искал, он должен выглядеть примерно следующим образом. не уверен, хотя.

SELECT `users`.`name`, * 
FROM users, actions 
JOIN < not sure what to put here > 
ORDER BY `actions`.`time` DESC 
< only one per user_id > 

Любая помощь будет оценена по достоинству.

+0

Ну, anwser уже принят, но у вас есть хорошая лекция, если вы хотите: http: // stackoverflow.com/questions/1907534/retrieve-2-last-posts-for-each-category – Savageman

ответ

1
SELECT * FROM users JOIN actions ON actions.id=(SELECT id FROM actions WHERE user_id=users.id ORDER BY time DESC LIMIT 1); 
+0

Любая конкретная причина, по которой вы используете подзапрос? Выглядит немного сложно для работы, нет? –

+2

В основном, незнание SQL, я использую подзапросы все время, когда я, вероятно, не должен :). Если есть лучший способ, вы должны отправить его как отдельный ответ. –

+0

Ну, честно говоря, я тоже не гуру SQL. Я думал, что у вас может быть какая-то гениальная причина, почему вы так делаете. ;-) –

0

выберите u.name, a.action, a.time
от пользователя щ действие по
, где u.id = a.user_id
и a.time в (выбрать макс (время) от действий, где user_id = u.user_id группы по user_id)



примечания непроверенной - но это должно быть рисунок на

1

вам нужно сделать GROUPWISE макс - пожалуйста, обратитесь к примерам здесь http://jan.kneschke.de/projects/mysql/groupwise-max/

вот пример я сделал для Сомон еще который похож на ваши требования:

http://pastie.org/925108

select 
u.user_id, 
u.username, 
latest.comment_id 
from 
users u 
left outer join 
(
    select 
    max(comment_id) as comment_id, 
    user_id 
    from 
    user_comment 
    group by 
    user_id 
) latest on u.user_id = latest.user_id; 
0
DECLARE @Table (ID Int, User_ID, Time DateTime) 

-- This gets the latest entry for each user 
INSERT INTO @Table (ID, User_ID, Time) 
SELECT ID, User_ID, MAX(TIME) 
FROM actions z 
INNER JOIN users x on x.ID = z.ID 
GROUP BY z. userID 

-- Join to get resulting action 
SELECT z.user_ID, z.Action 
FROM actions z 
INNER JOIN @Table x on x.ID = z.ID 
0

Это проблема величайшая-н-за группу, которая приходит часто на стек Переполнение. Следуйте тегу для десятков других сообщений по этой проблеме.

Здесь нет, как сделать это в MySQL дается ваша схема, без подзапросов и не GROUP BY:

SELECT u.*, a1.* 
FROM users u JOIN actions a1 ON (u.id = a1.user_id) 
LEFT OUTER JOIN actions a2 ON (u.id = a2.user_id AND a1.time < a2.time) 
WHERE a2.id IS NULL; 

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

0

Мне кажется, что следующее будет работа

WITH GetMaxTimePerUser (user_id, time) (
    SELECT user_id, MAX(time) 
    FROM actions 
    GROUP BY user_id 
) 
SELECT u.name, a.action, amax.time 
FROM actions AS a 
    INNER JOIN users AS u ON u.id=a.user_id 
    INNER JOIN GetMaxTimePerUser AS u_maxtime ON u_maxtime.user_id=u.id 
WHERE a.time=u_maxtime.time 

Использования временного имени результирующего набора (выражение общего стола или КТР) без подзапросов и OUTER JOIN путь лучше открыт для оптимизации запросов. (CTE - это что-то вроде VIEW, но существующего только виртуального или встроенного)