我有一个“会话”表,其他字段中包含以下字段:
int int(11),
user_id int(11),
login_date timestamp,
ip varchar(15)
我想为每个用户选择最后一个login_date和最后三个唯一的ips。我怎样才能以优雅的方式做到这一点?
我找到了一个解决方案,但它非常非常丑陋,无效,耗时并且涉及到mysql和bash脚本的混合。我怎么能只在MySQL中这样做?
P.S。该表有cc 430万行。
答案 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
然后你可以混合它们, 把它们放在一起会对资源有点沉重,但我认为这是可行的。
祝你好运!答案 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,您将拥有最新的用户登录信息。