MySQL 分组并仅从每个组中选择第一个

Att*_*tie 0 mysql greatest-n-per-group groupwise-maximum

我想执行一个查询,仅选择给定组中的最新项目。


在此示例中,我正在跟踪货车:

  • 每次他们返回基地时,check-in都会记录信息 - 里程等......
  • 每次他们送货时,delivery都会记录客户等......

该表让我们了解给定的历史记录van。数据可以通过查询生成或随时存储 - 这不是问题。

 id | checkin_id | delivery_id | van_id
----+------------+-------------+--------
 24 | 15         | NULL        | 3
 25 | NULL       | 28          | 3
 26 | 16         | NULL        | 4
 27 | NULL       | 29          | 3
 28 | NULL       | 30          | 4
 29 | 17         | NULL        | 5
Run Code Online (Sandbox Code Playgroud)

我可以通过使用 - 查询来查看货车的历史记录 ... WHERE van_id=3;

相反,我希望能够获得vans他们最近的“事件”的列表。结果是这样的:

 id | checkin_id | delivery_id | van_id
----+------------+-------------+--------
 27 | NULL       | 29          | 3
 28 | NULL       | 30          | 4
 29 | 17         | NULL        | 5
Run Code Online (Sandbox Code Playgroud)

我跳转到以下查询:

SELECT * FROM `history` GROUP BY `van_id`;
Run Code Online (Sandbox Code Playgroud)

但这会返回以下错误:

#1055 - SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含非聚合列“database.history.checkin_id”,该列在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容

读完后,我明白了这是怎么回事,并且不得不承认我的 SQL 有点过时了 -我想要返回组中的哪些项目?

添加checkin_iddelivery_idGROUP BY改变了问题 - 最终我得到了同一组数据,只是排序不同。


这个答案激起了我的兴趣,该图形确实有助于清楚地概述问题,谢谢@azerafati!

我想使用FIRST()orLAST()聚合函数 -但 MySQL 似乎没有它们

如何在不处理应用程序中的所有数据的情况下重现此行为?

O. *_*nes 9

我猜你的id值是独一无二的,后来的记录比早期的记录具有更高的值。

您需要使用一个子查询来获取id每辆货车的最新信息:

         SELECT MAX(id) id, van_id
           FROM history
          GROUP BY van_id
Run Code Online (Sandbox Code Playgroud)

然后将其加入到您的详细查询中。

 SELECT h.*
   FROM history h
   JOIN (
         SELECT MAX(id) id, van_id
           FROM history
          GROUP BY van_id
        ) m ON h.id = m.id AND h.van_id = m.van_id
Run Code Online (Sandbox Code Playgroud)

但因为你的 id 值是唯一的,你可以进一步简化它。

 SELECT h.*
   FROM history h
   JOIN (
         SELECT MAX(id) id
           FROM history
          GROUP BY van_id
        ) m ON h.id = m.id
Run Code Online (Sandbox Code Playgroud)