我在MySQL中有下表:
+-----------+------------+------------+------+-----------+
| user_name | session_id | status | data | timestamp |
+-----------+------------+------------+------+-----------+
| foo | 1 | start | 0 | 100 |
| foo | 1 | checkpoint | 15 | 120 |
| foo | 1 | stop | 46 | 130 |
| foo | 2 | start | 0 | 200 |
| foo | 2 | checkpoint | 97 | 210 |
+-----------+------------+------------+------+-----------+
我正在尝试执行一个查询,该查询从表中选择所有字段,并按session_id分组,并显示一组的结果为时间戳最大的行。
这是我要解决的问题,它无法完成工作,我正努力寻找从这里出发的地方:
select * from example where user_name = 'foo' and timestamp > 10 group by acct_session_id;
该语句产生如下内容:
+-----------+------------+------------+------+-----------+
| user_name | session_id | status | data | timestamp |
+-----------+------------+------------+------+-----------+
| foo | 1 | checkpoint | 15 | 120 |
| foo | 2 | start | 0 | 200 |
+-----------+------------+------------+------+-----------+
我希望得到的结果是
+-----------+------------+------------+------+-----------+
| user_name | session_id | status | data | timestamp |
+-----------+------------+------------+------+-----------+
| foo | 1 | stop | 46 | 130 |
| foo | 2 | checkpoint | 97 | 210 |
+-----------+------------+------------+------+-----------+
在该示例中,时间戳最大的行作为组的“顶部”返回。
此外,对于提供的所有答案,我将非常感谢有关正确索引的任何建议,以使该语句尽可能快地运行。我一直在努力思考用于诸如此类的复杂查询的正确索引。
*编辑
我已阅读在该线程上被标记为重复的线程上找到的答案,并尝试根据他们的问题定制它们,但没有成功。
首先,我尝试了链接线程的主要答案,更改了标识符以适合我的表:
WITH ranked_messages AS (
SELECT e.*, ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY timestamp DESC) AS rn
FROM example AS e
)
SELECT * FROM ranked_messages WHERE rn = 1;
我对此没有任何成功,在这一点上,我对声明的内容感到非常困惑。因此,接下来我在这里查看了有关窗口函数的文档:https://dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html
阅读这篇文章并没有我所希望的那么有用,但是我回到了链接线程并尝试了一些方法。
这是我得到的最近的东西:
SELECT e1.*
FROM example e1 LEFT JOIN example e2
ON (e1.session_id = e2.session_id AND e1.timestamp < e2.timestamp)
WHERE e2.timestamp IS NULL and e1.user_name = 'foo';
在我的小型测试表上,这产生了预期的答案,但是我在该表中只有一个user_name。我无法弄清楚如何更改此查询以仅在查询LEFT JOIN之前搜索特定的user_name,这是因为在我的生产表上,我有数百万行和数千个user_name,并且无法每次对每个用户执行此查询