PostgreSQL如何永久按date_time字段ASC排序表?可否使用RANK()函数?
解答
RANK()根本实现不了你要的表永久排序需求,别在这个函数上费功夫了。
先给你掰扯两个最基础的概念,搞懂就不会绕这个弯:
- 关系数据库里的表天生就是无序的行集合,压根没有「物理存储永久固定按某列排序」这回事。你平时不加
ORDER BY查出来的顺序,只是数据库当下读数据页的临时顺序,索引改了、数据增删了、数据库版本变了、执行计划换了,这个顺序随时可能变,半分准头都没有。 RANK()就是个用来算排名的窗口函数,只能在你跑查询的时候,给返回的结果集每行加个排名值,既不改原表数据,也不动存储结构,查询关了啥痕迹都留不下,跟「永久排序」半毛钱关系都没有。
对应你需求的正确做法
你对着自己的实际诉求选就行:
- 要是只是每次查数据都能拿到按
date_time升序的结果,别想什么歪招,老老实实写查询的时候加ORDER BY,这是唯一100%靠谱的方式:
SELECT id, name, date_time FROM 你的表名 ORDER BY date_time ASC;
- 看你给的期望结果里
id是从1重新排的连续值,原来id=3的最早数据排到了id=1的位置,要是你想要的是这个效果,也轮不到RANK()——RANK()遇到相同时间的行会给一样的排名,后面还会跳号,出不来连续编号,要用ROW_NUMBER():
SELECT ROW_NUMBER() OVER(ORDER BY date_time ASC) AS id, name, date_time FROM 你的表名;
你要是想把这个新编号永久更新到原表的id字段,拿这个逻辑套个UPDATE就行,但这也只是改了id字段的值,不是把表存成有序的,以后查的时候不加ORDER BY,顺序照样乱。
- 要是你是想让物理存储按
date_time排序,提升时间范围查询的速度,可以用数据库自带的聚簇功能:比如MySQL InnoDB把主键改成和date_time相关的字段,PostgreSQL用CLUSTER命令按date_time的索引重排表。但记住这都是一次性操作,之后增删改数据,数据库不会自动帮你维护物理顺序,时间长了还是乱,查的时候要有序还是得加ORDER BY。
最后提一句:只要你要的返回结果有顺序要求,就必须写
ORDER BY,不存在什么一劳永逸的「永久排序」能让你省掉这个子句,别在这上面踩坑。
内容的提问来源于stack exchange,提问作者Sanzy
相关产品推荐
相关产品推荐

