如何在每个用户的特定日期之前获取第一行以及在一次查询之后获取行?

时间:2014-07-05 15:05:22

标签: mysql sql fetch mariadb

我有表online_users_changes,我会在用户上线/空闲/离线时存储。

CREATE TABLE online_users_changes(id INT PRIMARY KEY AUTO_INCREMENT, user_id INT, timestamp TIMESTAMP, status TEXT);
INSERT INTO online_users_changes(user_id, timestamp, status) VALUES 
(1, "2014-07-05 9:00", "idle"),
(1, "2014-07-05 12:00", "online"),
(1, "2014-07-05 15:00", "offline"),
(2, "2014-07-05 7:00", "offline"),
(2, "2014-07-05 13:00", "online"),
(2, "2014-07-05 14:00", "offline");

我想创建图表,我会在特定的时间段内显示用户的状态。所以我需要获取此期间的所有更改+之前的最新更改。

SELECT * 
FROM online_users_changes 
WHERE timestamp >= :start and timestamp < :end
ORDER BY user_id, timestamp

此查询仅返回:start和:end之间的更改,但我还需要之前的最新更改:为每个用户启动。

如何获取我想要的数据?

http://sqlfiddle.com/#!2/8147a9/2

e.g。此查询

SELECT *
FROM online_users_changes 
WHERE timestamp BETWEEN "2014-07-05 11:00" and "2014-07-05 22:00" 
ORDER BY user_id, timestamp;

返回

| USER_ID |                   TIMESTAMP |  STATUS |
|---------|-----------------------------|---------|
|       1 | July, 05 2014 12:00:00+0000 |  online |
|       1 | July, 05 2014 15:00:00+0000 | offline |
|       2 | July, 05 2014 13:00:00+0000 |  online |
|       2 | July, 05 2014 14:00:00+0000 | offline |

但我希望得到类似的东西。

| USER_ID |                   TIMESTAMP |  STATUS |
|---------|-----------------------------|---------|
|       1 | July, 05 2014 09:00:00+0000 |    idle |
|       1 | July, 05 2014 12:00:00+0000 |  online |
|       1 | July, 05 2014 15:00:00+0000 | offline |
|       2 | July, 05 2014 07:00:00+0000 | offline |
|       2 | July, 05 2014 13:00:00+0000 |  online |
|       2 | July, 05 2014 14:00:00+0000 | offline |

3 个答案:

答案 0 :(得分:2)

“在给定日期之前的最近事件”=“在给定日期之前发生的第一个事件,当按反向时间顺序排序事件时”=

SELECT * FROM online_users_changes
WHERE timestamp < "your date and time here"
ORDER BY timestamp DESC
LIMIT 1

然后UNION这一行带有主查询。

注意,将ORDER BY子句与UNION一起使用有点棘手,你需要在正确的位置加上括号(manual pages拥有它们。)

答案 1 :(得分:1)

试试这个:

SELECT user_id, timestamp, status
FROM online_users_changes 
WHERE timestamp BETWEEN "2014-07-05 11:00" and "2014-07-05 22:00" 
Union
Select user_id, timestamp, status
From online_users_changes as temp
Where date(timestamp)="2014-07-05" and timestamp<"2014-07-05 11:00"
ORDER BY user_id, timestamp;

答案 2 :(得分:1)

你可以尝试这个(非常类似于bitsm帖子):

 select user_id, Max(timestamp) as timestamp, status
 FROM online_users_changes 
 WHERE timestamp < "2014-07-05 11:00"
 group by user_id, status
 union all
 SELECT user_id, timestamp, status
 FROM online_users_changes 
 WHERE timestamp BETWEEN "2014-07-05 11:00" and "2014-07-05 22:00" 
 ORDER BY user_id, timestamp;

这是适合你的方式。

http://sqlfiddle.com/#!2/8147a9/8

<强>更新 我根据给出的新数据尝试了以下更新。它可能需要一些清理,因为我个人认为查询看起来很讨厌,尽管它在工作上取得了成功。

 SELECT user_id, max(timestamp) as timestamp, status 
 from (SELECT user_id, timestamp, status 
  FROM online_users_changes
  WHERE timestamp < "2014-07-05 11:00"
  GROUP BY user_id, status
 ) a
 group by user_id
 union all
 (SELECT user_id, timestamp, status
 FROM online_users_changes 
 WHERE timestamp BETWEEN "2014-07-05 11:00" and "2014-07-05 22:00" )
 ORDER BY user_id, timestamp;

SQL小提琴。 http://sqlfiddle.com/#!2/0bd390/44

如果有人有任何其他建议,请随时提供其他建议。