MySQL如何分组,并显示该组中指定列最大的行

时间:2019-03-24 21:53:48

标签: mysql greatest-n-per-group

我在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,并且无法每次对每个用户执行此查询

0 个答案:

没有答案