根据另一篇SO帖子(SQL:如何使用DISTINCT保持行顺序?),就排序而言,distinct具有相当不确定的行为.
我有一个问题:
select col_1 from table order by col_2
Run Code Online (Sandbox Code Playgroud)
这可以返回值
3
5
3
2
Run Code Online (Sandbox Code Playgroud)
我需要在这些上选择一个保留排序的不同,这意味着我想要
select distinct(col_1) from table order by col_2
Run Code Online (Sandbox Code Playgroud)
回来
3
5
2
Run Code Online (Sandbox Code Playgroud)
但不是
5
3
2
Run Code Online (Sandbox Code Playgroud)
这是我实际上要做的事情.Col_1是用户ID,col_2是该用户的登录时间戳事件.因此,同一个用户(col_1)可以有很多登录时间.我正在尝试构建一个在系统中看到它们的用户的历史列表.我希望能够说"我们的第一个用户是,我们的第二个用户曾经是",依此类推.
该帖子似乎建议使用group by,但group by并不意味着返回行的排序,所以我不知道这将如何或为什么适用于此,因为它不会出现group by将保留任何排序.实际上,另一个SO帖子给出了一个示例,其中group by将破坏我正在寻找的顺序:请参阅"Peter",其中GROUP BY和ORDER BY在sql中有什么区别.无论如何要保证后者的结果吗?奇怪的是,如果我正在实现DISTINCT子句,我肯定会先执行命令,然后取结果并对列表进行线性扫描并自然保留顺序,所以我不确定为什么行为如此未定义.
编辑:
谢谢你们!我接受了IMSoP的答案,因为不仅有一个我可以使用的交互式示例(感谢我转向SQL Fiddle),但他们也解释了为什么有些事情按照他们的工作方式工作,而不仅仅是"做这个" .具体来说,不清楚GROUP BY不会在组外的其他列中销毁(而是将它们保留在某种内部列表中)值,并且仍然可以在ORDER BY子句中检查这些值.
IMS*_*SoP 10
这一切都与SQL语句的"逻辑排序"有关.虽然DBMS可能实际上根据各种聪明的策略检索数据,但它必须根据某些可预测的逻辑来运行.因此,根据逻辑的行为方式,可以认为SQL查询的不同部分在"之前"或"之后"彼此处理.
碰巧的是,该ORDER BY子句是该逻辑序列中的最后一步,因此它不能改变"早期"步骤的行为.
如果使用a GROUP BY,那么在SELECT子句运行时行已经捆绑到它们的组中,更不用说了ORDER BY,所以你只能查看已经分组的列,或"聚合"在所有值中计算的值.一组.(MySQL实现了一个有争议的扩展GROUP BY,你可以在那里提到一个SELECT逻辑不存在的列,它将从该组中的任意行中选择一个).
如果你使用a DISTINCT,它会在之后进行逻辑处理SELECT,但ORDER BY之后仍然会出现.因此,只有在DISTINCT抛弃重复项后,剩余的结果才会被置于特定的顺序中 - 但已丢弃的行不能用于确定该顺序.
至于如何获得所需的结果,关键是要找到一个值,以便在/ has(逻辑)运行之后对其进行排序.请记住,如果使用a ,则任何聚合值仍然有效 - 聚合函数可以查看组中的所有值.这包括和,它是理想的排序,因为"最低数字"()与"第一个数字,如果我按升序排序"相同,反之亦然.GROUP BYDISTINCTGROUP BYMIN()MAX()MINMAX
因此,要foo_number根据适用bar_number于每个值的最低值来排序一组不同的值,您可以使用:
SELECT foo_number
FROM some_table
GROUP BY foo_number
ORDER BY MIN(bar_number) ASC
Run Code Online (Sandbox Code Playgroud)
编辑:在评论中,讨论了为什么,如果在分组/重复数据删除发生之前应用了排序,则该顺序不会应用于组.如果是这种情况,您仍然需要一个策略,在每个组中保留哪一行:第一个或最后一个.
作为类比,将原始行集描绘成从牌组中挑选的一组扑克牌,然后按其面值从低到高排序.现在,穿过分类的甲板,将它们分成一堆,分别用于每件套装.哪张卡应该"代表"每一堆?
如果发牌面朝上,显示出在最后的卡将具有的那些最高面值("保持最后的"战略); 如果你面朝下处理然后翻转每一堆,你将揭示最低的面值("先保持"策略).两者都遵守卡片的原始顺序,并且"基于套装处理卡片"的说明不会自动告诉经销商(代表DBMS)策略的目的.
如果卡的最终桩是从一个组GROUP BY,然后MIN()和MAX()代表拿起每根桩,寻找最低或最高值,无论他们是在顺序的.但因为你可以看看组里面,你可以做其他事情也就是说,比如加起每个桩的总价值(SUM)或者有多少卡(COUNT)等,GROUP BY比"有序DISTINCT" 更强大.
| 归档时间: |
|
| 查看次数: |
5045 次 |
| 最近记录: |