使用 SQL 查询(MySQL 数据库)获取不同项目的最新“事件”
Posted
技术标签:
【中文标题】使用 SQL 查询(MySQL 数据库)获取不同项目的最新“事件”【英文标题】:Get the most recent "event" for distinct items using an SQL query (MySQL database) 【发布时间】:2015-01-02 04:39:38 【问题描述】:我有一个“事件”表,用于存储有关实验室计算机登录、注销、关机和启动的一些统计数据。
我希望生成的是最后个每个人计算机名所做的操作列表。
这是我的名为 raw 的表的示例:
mysql> select * from raw limit 20;
+--------+--------------+-------+---------------------+
| id | computername | event | timestamp |
+--------+--------------+-------+---------------------+
| 148776 | REF-18 | 1 | 2014-11-05 15:05:29 |
| 148775 | DEC-02 | 3 | 2014-11-05 15:05:19 |
| 148774 | GPS-06 | 3 | 2014-11-05 15:05:18 |
| 148773 | DEC-15 | 3 | 2014-11-05 15:05:16 |
| 148772 | DEC-02 | 1 | 2014-11-05 15:04:33 |
| 148771 | REF-18 | 2 | 2014-11-05 15:04:18 |
| 148770 | REF-09 | 1 | 2014-11-05 15:04:14 |
| 148769 | REF-18 | 4 | 2014-11-05 15:04:02 |
| 148768 | DEC-02 | 2 | 2014-11-05 15:03:39 |
| 148767 | DEC-02 | 4 | 2014-11-05 15:03:24 |
| 148766 | REF-09 | 2 | 2014-11-05 15:03:00 |
| 148765 | DEC-08 | 3 | 2014-11-05 15:02:54 |
| 148764 | REF-09 | 4 | 2014-11-05 15:02:44 |
| 148763 | REF-09 | 3 | 2014-11-05 15:01:31 |
| 148762 | DEC-01 | 1 | 2014-11-05 15:01:13 |
| 148760 | REF-19 | 1 | 2014-11-05 15:00:50 |
| 148761 | DEC-04 | 3 | 2014-11-05 15:00:50 |
| 148759 | REF-18 | 3 | 2014-11-05 15:00:25 |
| 148758 | DEC-36 | 1 | 2014-11-05 15:00:10 |
| 148757 | DEC-01 | 2 | 2014-11-05 15:00:09 |
+--------+--------------+-------+---------------------+
我想出了几个我认为可行的解决方案;
SELECT r1.id, r1.computername, r1.event, r1.timestamp
FROM raw r1
JOIN (SELECT id, computername, event, MAX(timestamp) AS timestamp
FROM raw GROUP BY computername)
AS r2
ON r1.computername = r2.computername
AND r1.timestamp = r2.timestamp
GROUP BY r1.computername;
这似乎可以完成这项工作,但它需要f o r e v e r
SELECT *
FROM (SELECT * from raw order by timestamp desc) row_result
GROUP BY computername;
到目前为止,这花费的时间要少得多,但似乎产生了相同的结果。哪个更好?第二个查询仅仅是对 MySQL 工作方式的hack 吗?我可以优化我的数据,或者以某种方式查询以产生更快更可靠的结果吗?
谢谢!
【问题讨论】:
第二个查询只有在您对时间戳非常幸运时才有效。 当事情永远不会发生时,发布EXPLAIN
的结果以供您查询,以查看您的查询是如何执行的。这几乎总是缺少索引和无情的表扫描的情况。
你应该尝试为诸如此类的问题提供一个 sql fiddle(至少在我看来),以使可能的回答者更容易 - 因为我们中的许多人可能最终还是单独做.
适当索引,您的第一个查询应该非常非常快。与第二个查询相比,它具有被记录的优势,虽然这里的一些人很受欢迎,但正如您所猜测的那样,它是一个未记录的黑客攻击。
...此外,在子查询中包含 id 和 event 似乎没有任何目的,在外部查询中也包含 GROUP BY 子句
【参考方案1】:
你有没有尝试过这样的事情:
select r.id, r.computername, r.event, r.timestamp
from raw r
inner join (
select max(id) as id
from raw
group by computerName
) as maxEventPerComputer on r.id = maxEventPerComputer.Id
当然,它与您的初始查询非常相似,但您可能会得到更好的结果,特别是考虑到您的 id 列(可能)被索引到您的日期列可能不在的位置(我想)。
但据我了解,与其他 RDBMS 相比,mysql 的子查询不太好......但希望这会有所帮助。
【讨论】:
这是 LOADS 更快...非常感谢。这似乎确实是最好的解决方案。我真的应该考虑一下我可以拉 MAX(id) 的事实,因为它无论如何都是有罪的。以上是关于使用 SQL 查询(MySQL 数据库)获取不同项目的最新“事件”的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Azure SQL db 中的存储过程一次性获取查询的所有批次?