最新访客

时间:2010-01-12 17:31:04

标签: php mysql

假设您要在用户个人资料页面上显示最新访问者。 你会如何构建这个?也许是一个名为uservisitors的表:

  • userid(访问的用户)
  • visitorid(访客)
  • 时间

你怎么用mysql选择这个?没有任何重复,我的意思是如果用户1访问用户2的个人资料,然后5分钟后再次访问,我不希望它只显示两个条目最新

喝彩!

6 个答案:

答案 0 :(得分:4)

SELECT  visitorid, MAX(time) AS lastvisit
FROM    uservisitors
WHERE   userid = ?
GROUP BY
        userid, visitorid
ORDER BY
        lastvisit DESC
LIMIT 5

(userid, visitorid, time)上创建一个复合索引,以便更快地工作。

此查询:

SELECT  visitorid
FROM    uservisitors ui
WHERE   userid = ?
        NOT EXISTS
        (
        SELECT  NULL
        FROM    uservisitors uo
        WHERE   uo.userid = ui.userid
                AND uo.visitorid = ui.visitorid
                AND uo.time > ui.time
        )
ORDER BY
        time DESC
LIMIT 5
如果你有很多不同的访问者,

可能会更有效率。

在这种情况下,您需要(userid, time, visitorid)上的索引。

<强>更新

我的博客中的这篇文章比较了两种方法:

答案 1 :(得分:0)

这样的事情应该有效:

SELECT visitorid, MAX(time)
FROM uservisitors
WHERE userid = 1
GROUP BY visitorid

答案 2 :(得分:0)

在过去5分钟内找到不同的访问者。 您可以将INTERVAL更改为过去24小时内的任何时间段,例如INTERVAL 1 DAY。

SELECT distinct visitorid 
FROM uservisitors
WHERE userid = 1 AND time > DATE_SUB(NOW(), INTERVAL 5 MIN);

答案 3 :(得分:0)

假设您只关心访问者的最后一次访问而不是所有访问,那么如何为userid / visitorid使用唯一密钥对,然后使用INSERT INTO ..在DUPLICATE KEY:

CREATE TABLE uservisitors (... UNIQUE (userid, visitorid) );
INSERT INTO uservisitors (userid, visitorid, time) VALUES (....) ON DUPLICATE KEY UPDATE time=NOW();

然后一个简单的选择来获得前5名访客:

SELECT visitorid FROM uservisitors WHERE user_id=1 ORDER BY time DESC LIMIT 5;

没有重复记录或必须使用分组。

答案 4 :(得分:0)

您打算如何从表中删除内容?您可能需要为此添加另一个索引才能有效工作。

如果你只想要最后5次访问,我会对表进行反规范化(节省空间,索引并且只使用一个主键查找),在这个过程中,我不再需要担心删除旧数据。每个用户只占用表中的一行,因此随着时间的推移不会增长太多。所以:

CREATE TABLE user_visitors (user_id int primary key,
visitor_1_id int,
visitor_1_time timestamp,
..
visitor_5_id int,
visitor_5_time timestamp);

要存储访问权限,您可以使用visitor_1作为访问者插入新行。在重复项上,您将向下移动先前存储的值:

INSERT INTO user_visitors SET ... 
... ON DUPLICATE KEY UPDATE visitor_5_id = visitor_4_id, visitor_5_time = visitor_4_time ...
... visitor_1_id = ?, visitor_1_time = ?

如果您担心重复,可以通过在UPDATE部分中添加IF来解决这个问题,这样如果该行中已存在visitor_id,则该行将不会更新。在代码中,您可以检查更新的行数。如果为零,则从那里处理重复的访问者时间更新。它涉及一些工作,但它将快速且易于理解。

答案 5 :(得分:0)

我已经处理了几次,这是我对它的看法。

我的表格如下:

CREATE TABLE visitors (
userid int,
visitorid int,
last_visit datetime,
primary key(userid, visitorid),
index(visitorid)
index(userid, last_visit)
) engine = memory;

插入数据:

INSERT INTO visitors (userid, last_visit) VALUES ( 50, now() ) 
ON DUPLICATE KEY UPDATE last_visit = now();

选择

select * from visitors WHERE userid=10 order by last_visit limit 10; # or whatever you need

偶尔清除表格

DELETE from visitors WHERE last_visit < date_add(now(), INTERVAL -1 WEEK);

这是出于某些原因的方法。

  1. 您正在使用内存表,因此您永远不会触摸磁盘。
  2. 索引已打开(visitorid,last_update),因此它是纯索引查找。非常快。即使没有它,也应该很快。
  3. 通过单独的查询拉取用户将允许您缓存它们,但理论上,如果他们最近访问过该网站,则应该已经缓存它们。即使您没有使用缓存,对用户(主键)的in()查询应该非常快。
  4. 你可以运行一个cron来每分钟备份一次这个表

    SELECT * from visitors INTO OUTFILE "/tmp/visitors.txt"