最近工作中有遇到查询分组第一条的问题,由此想到了一些关于 select 返回数据的顺序的几个问题。
select 返回数据的顺序在没有指定排序的情况下是不确定的,是一个集合。集合本身是没有顺序的!!
数据内容如下:
id page_id addtime
1 1 1558342663
2 1 1558348337
3 1 1558349079
4 2 1558348351
5 4 1558348372
6 3 1558348361
7 1 1558349140
8 1 1558399247
9 3 1558349702
10 1 1558399412
11 1 1558402590
12 1 1558408852
1. 对select的结果没有任何条件进行select,顺序是怎么样?
对于查询结果集直接进行select查询,特别是已排序的结果集,会改变数据的顺序。
query 1:
id page_id addtime
12 1 1558408852
11 1 1558402590
10 1 1558399412
8 1 1558399247
9 3 1558349702
7 1 1558349140
3 1 1558349079
5 4 1558348372
6 3 1558348361
4 2 1558348351
2 1 1558348337
1 1 1558342663
query 2:
id page_id addtime
1 1 1558342663
2 1 1558348337
3 1 1558349079
4 2 1558348351
5 4 1558348372
6 3 1558348361
7 1 1558349140
8 1 1558399247
9 3 1558349702
10 1 1558399412
11 1 1558402590
12 1 1558408852
2.先排序再分组,能否获取到分组第一条数据?
对于分组获取第一条数据,很多博客给的方案是先对数据进行排序,再对结果集进行分组,这样就能够获取到分组的第一条数据了。说实话,这个很符合逻辑,我之前确实也是这么想的。但是前提是排完序,到分组前,数据的顺序依然是排序后的顺序才可以。
第一个问题,其实已经说明了,对于一个排完序的结果集载进行一次查询,查询结果的顺序是会变化的,跟内层排序结果集并不是一致的。所以我们在顺序不正确的数据上进行分组,拿到的数据也必然是不准确的。
还是以最初的数据为例,需要按page_id进行分组,取每组中addtime最大的一条数据,正确的结果应该是:
id page_id addtime
12 1 1558408852
9 3 1558349702
5 4 1558348372
4 2 1558348351
第一条sql,先排序,然后对结果集进行分组操作得到的结果是
id page_id addtime
1 1 1558342663
4 2 1558348351
6 3 1558348361
5 4 1558348372
第二条sql,先排序,然后对结果集进行分组操作并排序
id page_id addtime
5 4 1558348372
6 3 1558348361
4 2 1558348351
1 1 1558342663
第三条sql,先分组再排序
id page_id addtime
5 4 1558348372
6 3 1558348361
4 2 1558348351
1 1 1558342663
可以看出,先排序再分组操作,并不能取得分组中的第一条数据!!!
如果想要获取分组中第一条,先分组,获取分组中排序字段最大或最小的排序字段值(addtime),然后通过排序字段(addtime),分组字段(page_id)与原数据进行连表操作,取出其他字段的数据。