选择最后N个唯一记录mysql

时间:2013-07-10 08:20:36

标签: mysql sql

我有一个“会话”表,其他字段中包含以下字段:

int int(11),
user_id int(11),
login_date timestamp,
ip varchar(15)

我想为每个用户选择最后一个login_date和最后三个唯一的ips。我怎样才能以优雅的方式做到这一点?

我找到了一个解决方案,但它非常非常丑陋,无效,耗时并且涉及到mysql和bash脚本的混合。我怎么能只在MySQL中这样做?

P.S。该表有cc 430万行。

一些示例数据:http://sqlfiddle.com/#!2/e9ddd

3 个答案:

答案 0 :(得分:3)

花费大量时间从MYSQL

转换SQL SERVER

我的查询工作是更好的效果

select 
user_id,
max(cast(login_date as datetime)),
group_concat(distinct ip order by login_date desc SEPARATOR  ' , ')
from 
(
SELECT 
  user_id,
  login_date,
  ip,
  CASE user_id 
   WHEN @curType 
    THEN @curRow := @curRow + 1 
    ELSE @curRow := 1 AND @curType := user_id 
  END as sequence
FROM sessions, (SELECT @curRow := 0, @curType := '') r
ORDER BY user_id asc,login_date desc
)t
where sequence<4
group by user_id

<强> SQL FIDDLE

答案 1 :(得分:0)

这将为您提供每个user_id的最后日期

SELECT s1.* FROM sessions s1 
LEFT OUTER JOIN sessions s2
ON s1.user_id = s2.user_id AND s1.login_date < s2.login_date
WHERE s2.user_id IS NULL

这将获得用于每个user_id的唯一IP

SELECT user_id, GROUP_CONCAT(DISTINCT(ip)) FROM sessions GROUP BY user_id

然后你可以混合它们, 把它们放在一起会对资源有点沉重,但我认为这是可行的。

祝你好运!

http://sqlfiddle.com/#!2/bb209/71

答案 2 :(得分:0)

你可以这样做:

SELECT * FROM (
  SELECT 
    user_id
    ,ip, 
    ,login_date
    ,IF(@user_id = SESSION_GRUOPED.user_id, @rownum:=@rownum+1, @rownum:=1 ) as row_id
    ,(@user_id:= SESSION_GRUOPED.user_id) as group_id
  FROM (
    SELECT user_id, ip, max(login_date) login_date FROM SESSION group by user_id, ip order by user_id, login_date desc
  ) SESSION_GRUOPED 
    JOIN  (SELECT @rownum := 0) r
    JOIN  (select @user_id := 0) u
) RESULT
WHERE row_id < 4;

查询的关键是这部分

SELECT user_id, ip, max(login_date) login_date FROM SESSION group by user_id, ip order by user_id, login_date desc

由于这个原因,您可以获得每个用户在给定ip上登录的信息。

然后你将它包装起来在组中设置结果编号,然后你只需将结果限制为小于4的结果,因为你只想要单个用户的三个结果。

注意:如果更改row_id&lt; 4进入row_id = 1,您将拥有最新的用户登录信息。