使用LEFT JOIN,GROUP BY和ORDER BY进行MySQL查询

时间:2012-01-17 11:49:40

标签: mysql group-by sql-order-by left-join

我有两个表,UsersVisitors。在Users中,我拥有所有用户信息,并在Visitors中输入了登录结果。每次用户登录时,新记录都会Visitorsuser_id进入datetime

我想使用上次登录的 datetime 选择所有用户。我怎么能这样做?

3 个答案:

答案 0 :(得分:2)

为避免使用子查询计算每个用户的最近时间(这实际上意味着对n个用户运行n个查询),请使用group by的mysql“技巧” 没有聚合,它返回每个组的第一行行:

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;

此查询将执行得非常好,只需对访问表9进行一次传递,每个用户都没有子查询。

以下是对正在发生的事情的分解:

  • 最内层查询(别名为x)按顺序获取用户ID和last_visit,并在每个用户ID中使用 first 的last_visit值
  • 下一个查询(别名为y)在用户ID 上使用group by,而不使用使用任何聚合函数。在其他数据库中,这将是一个错误,但是对于mysql,它返回每个组的第一个行 - 即我们想要的last_visit值(因此刚刚对行进行了排序)
  • 最终的最外层查询会对这些结果执行left join,为从未访问过的用户提供null值,否则会将我们想要加入的last_visit加入用户行

答案 1 :(得分:1)

尝试在选择

中使用子查询

例如: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;

答案 2 :(得分:0)

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子句中,您声明不能有以后的行。这只给你最新的一行。

如果有多个具有相同时间戳的电子邮件, 这个查询需要精炼。如果电子邮件表中有增量ID列, 更改JOIN,如:

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