MySQL запрос с LEFT JOIN, GROUP BY и ORDER BY - PullRequest
1 голос
/ 17 января 2012

У меня есть две таблицы, Users и VisitorsUsers у меня есть вся информация о пользователе, а в Visitors я помещаю результаты входа в систему.Каждый раз, когда пользователь входит в систему, новая запись заносится в Visitors с user_id и datetime.

. Я хочу выбрать всех пользователей с datetime последнего логина.Как я могу это сделать?

Ответы [ 3 ]

2 голосов
/ 17 января 2012

Чтобы избежать использования подзапросов для вычисления самого последнего времени для каждого пользователя (что фактически означало бы выполнение n запросов для n пользователей), используйте "трюк" mysql для group by без агрегат, который возвращает первую строку каждой группы:

select u.*, last_login
from users u
left join (select id, last_login 
  from (select u.id, v.last_login
    from users u
    join visits v on v.user_id = u.id
    order by 1, 2 desc
  ) x
group by 1) y on y.id = u.id;

Этот запрос будет работать очень хорошо, сделав всего один проход по таблице посещений (для каждого пользователя нет подзапросов).

Вот пример того, что происходит:

  • Самый внутренний запрос (с псевдонимом x) получает идентификатор пользователя и last_visit в соответствии со значением last_visit, которое мы хотим first внутри каждого идентификатора пользователя
  • В следующем запросе (с псевдонимом y) используется group by для идентификатора пользователя без с использованием любых функций агрегирования.В других базах данных это было бы ошибкой, но с mysql он возвращает первую строку каждой группы - то есть значение last_visit, которое мы хотим (просто упорядочив таким образом строки)
  • Final,самый внешний запрос делает left join для этих результатов, давая значение null для пользователей, которые никогда не посещали, иначе давая last_visit, который мы хотим присоединить к строке пользователя
1 голос
/ 17 января 2012

попробуйте использовать подзапрос в select

, например: select u.name,(select datetime from visitors v where u.id_user = v.id_user order by datetime desc limit 1) as lastlogin_datetme from users u;

0 голосов
/ 22 октября 2012
SELECT cur.textID, cur.fromEmail, cur.subject, 
     cur.timestamp, cur.read
FROM incomingEmails cur
LEFT JOIN incomingEmails next
    on cur.fromEmail = next.fromEmail
    and cur.timestamp < next.timestamp
WHERE next.timestamp is null
and cur.toUserID = '$userID' 
ORDER BY LOWER(cur.fromEmail)

Basically, you join the table on itself, searching for later rows.

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

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

LEFT JOIN incomingEmails next
    on cur.fromEmail = next.fromEmail
    and cur.id < next.id
...