在MySQL中,如何查询“last inserted row equals”?

时间:2015-08-20 03:32:46

标签: mysql sql database indexing

mysql> desc accounts_users;
+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | int(11)      | NO   | PRI | NULL    | auto_increment |
| login_at               | datetime     | YES  |     | NULL    |                |
| logout_at              | datetime     | YES  |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql> desc rooms_events;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| user_id    | int(11)      | NO   | MUL | NULL    |                |
| event      | varchar(255) | NO   | MUL | NULL    |                |
| created_at | datetime     | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

当用户执行操作时,我向rooms_events表添加“event”行。事件列可以是“创建”或“销毁”。没有唯一的列。

我想查询:

  

查找最新事件所在的所有唯一user_id   “创建”AND尚未登录(login_at)24小时。

如何执行此类查询?

2 个答案:

答案 0 :(得分:1)

我会说可以这样查询:

SELECT DISTINCT U.id
FROM    accounts_users U
INNER JOIN rooms_events E ON U.id = E.user_id
WHERE   U.login_at < DATE_SUB(NOW(),INTERVAL 24 HOUR)
        AND E.created_at IN (
            SELECT MAX(created_at)
            FROM rooms_events
            GROUP BY user_id
           )
        AND E.`event` = 'create';

我不是100%确定子查询在各种可能的情况下都能完成它的工作,但是有一些测试数据可以在我的机器上运行。

答案 1 :(得分:0)

SELECT user_id
    FROM rooms_events c
    WHERE NOT EXISTS (
                 SELECT *
                     FROM room_events
                     WHERE event = 'create'
                       AND user_id = c.user_id
                       AND created_at > c.created_at )
      AND NOT EXISTS (
                 SELECT *
                     FROM accounts_users
                     WHERE id = c.user_id
                       AND login_at > NOW() - INTERVAL 24 HOUR;

指数:

room_events:  INDEX(event, user_id, created_at)

这假设created_atevent的时间。

由于您似乎只记录了最新的登录信息,因此可以简化为:

SELECT u.id
    FROM rooms_events c
    JOIN account_users u  ON c.user_id = u.id
    WHERE u.login_at < NOW() - INTERVAL 24 HOUR
      AND NOT EXISTS (
                 SELECT *
                     FROM room_events
                     WHERE event = 'create'
                       AND user_id = c.user_id
                       AND created_at > c.created_at )

如果您希望有大量旧数据,那么INDEX(login_at, id)可能会有所帮助。

如果event只能是两个值,请考虑ENUM('create', 'destroy') NOT NULL

对于room_events(user_id, event)不是唯一的吗?因此它可能是PRIMARY KEY(并且摆脱id)。如果进行了更改,则不需要我建议的索引。