【发布时间】:2018-12-29 02:17:41
【问题描述】:
我想执行一个查询,只选择给定组中的最新项目。
在这个例子中,我正在跟踪货车:
- 每次他们返回基地时,都会记录一个
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
我可以通过... WHERE van_id=3; 查询来查看货车的历史记录 - 很好。
相反,我希望能够获得vans 的列表以及他们最近的“事件”。结果是这样的:
id | checkin_id | delivery_id | van_id
----+------------+-------------+--------
27 | NULL | 29 | 3
28 | NULL | 30 | 4
29 | 17 | NULL | 5
我跳转到以下查询:
SELECT * FROM `history` GROUP BY `van_id`;
但这会返回以下错误:
#1055 - SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含非聚合列“database.history.checkin_id”,它在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容
阅读后,我明白这是什么意思,并且不得不承认我的 SQL 有点过时了 - 我希望返回组中的哪些项目?
将checkin_id 和delivery_id 添加到GROUP BY 只会改变问题 - 最终我会得到相同的数据集,只是排序不同。
This answer 引起了我的兴趣,该图确实有助于清晰地勾勒出问题,感谢@azerafati!
我想使用 FIRST() 或 LAST() 聚合函数 - but MySQL doesn't appear to have them。
如何在不处理应用程序中的所有数据的情况下重现此行为?
【问题讨论】:
-
学会正确使用
GROUP BY。那么你就不会出现这个错误了。 -
你得到这个特定错误的原因是因为 MySQL 的最新版本默认不允许它。据我所知,MySQL 是唯一允许它的 RDBMS。问题是,除非选择的非分组、非聚合字段在“功能上依赖于”分组字段,否则所使用的值不能保证是遇到的特定值(实际上是从分组过程中遇到的那些随机选择)。基本上,如果您的配置允许,您的查询可能会得到类似 (27, 15, 28, 3) 的结果行。
-
你可以看出你的代码没有意义。当您按
van_id分组时,您没有对checkin_id和delivery_id进行聚合,MySQL 怎么知道要获取哪一个?对于van_id 3,为什么checkin_id是NULL,而不是15?为什么delivery_id是29,而不是NULL??? -
您正在尝试使用 MySQL 已弃用的非标准扩展
GROUP BY。请阅读this。
标签: mysql greatest-n-per-group