row_number函数的不稳定性

举报
nullptr_ 发表于 2023/09/01 16:34:17 2023/09/01
【摘要】 row_number窗口函数的排序是不稳定排序,行的物理顺序可能会发生变化,通过巧妙的构思实现排序的稳定

row_number为窗口函数,用来为各组内数据生成连续排号

基础用法

postgres=# select id,name,age,row_number() over() from test;
 id | name | age | row_number
----+------+-----+------------
  2 | 张三 |  13 |          1
  3 | 张四 |  16 |          2
  3 | 张三 |  14 |          3
  1 | 张三 |  12 |          4
  3 | 张四 |  15 |          5
(5 rows)    
postgres=# select id,name,age,row_number() over(order by age) from test;
 id | name | age | row_number
----+------+-----+------------
  3 | 张四 |  16 |          5
  3 | 张三 |  14 |          3
  3 | 张四 |  15 |          4
  1 | 张三 |  12 |          1
  2 | 张三 |  13 |          2
(5 rows)
postgres=# select id,name,age,row_number() over(partition by name order by age) from test;
 id | name | age | row_number
----+------+-----+------------
  1 | 张三 |  12 |          1
  2 | 张三 |  13 |          2
  3 | 张三 |  14 |          3
  3 | 张四 |  15 |          1
  3 | 张四 |  16 |          2
(5 rows)

特殊用法

postgres=# select * from test1 where id in (1,2,4);
 id |                                                                                                          info
----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2 | 张三,12;张三,13;张三,14
  1 | 张四,13;张四,16;张四,17
  4 | 张十一,14;张十一,13;张十一,16;张十一,146;张十一,136;张十一,166;张十一,46;张十一,36;张十一,66;张十一,246;张十一,236;张十一,26;张十一,36;张十一,76;张十一,17;张十一,13;张十一,15;张十一,19;张十一,10;张十一,6;张十一,966
(3 rows)

需求:将表中info字段转成行,并按照存储顺序生成组内序号。
将字段info 通过函数regexp_split_to_table用分号作为分隔符转成行,通过split_part将各行分段输出

postgres=#  select split_part(c.a,',',1) as name, split_part(c.a,',',2) as age from (select regexp_split_to_table(info,';') as a  from test1 where id in (1,2,4)) c;
  name  | age
--------+-----
 张十一 | 14
 张十一 | 13
 张十一 | 16
 张十一 | 146
 张十一 | 136
 张十一 | 166
 张十一 | 46
 张十一 | 36
 张十一 | 66
 张十一 | 246
 张十一 | 236
 张十一 | 26
 张十一 | 36
 张十一 | 76
 张十一 | 17
 张十一 | 13
 张十一 | 15
 张十一 | 19
 张十一 | 10
 张十一 | 6
 张十一 | 966
 张四   | 13
 张四   | 16
 张四   | 17
 张三   | 12
 张三   | 13
 张三   | 14
(27 rows)

增加组内行号

postgres=# select split_part(c.a,',',1) as name, split_part(c.a,',',2) as age,row_number() over (partition by name)  from (select regexp_split_to_table(info,';') as a  from test1 where id in (1,2,4)) c;
  name  | age | row_number
--------+-----+------------
 张三   | 12  |          1
 张三   | 13  |          2
 张三   | 14  |          3
 张十一 | 966 |          1
 张十一 | 19  |          2
 张十一 | 10  |          3
 张十一 | 6   |          4
 张十一 | 14  |          5
 张十一 | 13  |          6
 张十一 | 16  |          7
 张十一 | 146 |          8
 张十一 | 136 |          9
 张十一 | 166 |         10
 张十一 | 46  |         11
 张十一 | 36  |         12
 张十一 | 66  |         13
 张十一 | 246 |         14
 张十一 | 236 |         15
 张十一 | 26  |         16
 张十一 | 36  |         17
 张十一 | 76  |         18
 张十一 | 17  |         19
 张十一 | 13  |         20
 张十一 | 15  |         21
 张四   | 16  |          1
 张四   | 17  |          2
 张四   | 13  |          3
(27 rows)

可见行号并非按照存储顺序进行赋值,使用sequence进行优化可实现相关需求

postgres=# create sequence test_seq;
CREATE SEQUENCE
postgres=# select split_part(c.a,',',1) as name, split_part(c.a,',',2) as age,row_number() over (partition by name order by c.line)  from (select nextval('test_seq') as line, regexp_split_to_table(info,';') as a  from test1 where id in (1,2,4)) c;
  name  | age | row_number
--------+-----+------------
 张三   | 12  |          1
 张三   | 13  |          2
 张三   | 14  |          3
 张十一 | 14  |          1
 张十一 | 13  |          2
 张十一 | 16  |          3
 张十一 | 146 |          4
 张十一 | 136 |          5
 张十一 | 166 |          6
 张十一 | 46  |          7
 张十一 | 36  |          8
 张十一 | 66  |          9
 张十一 | 246 |         10
 张十一 | 236 |         11
 张十一 | 26  |         12
 张十一 | 36  |         13
 张十一 | 76  |         14
 张十一 | 17  |         15
 张十一 | 13  |         16
 张十一 | 15  |         17
 张十一 | 19  |         18
 张十一 | 10  |         19
 张十一 | 6   |         20
 张十一 | 966 |         21
 张四   | 13  |          1
 张四   | 16  |          2
 张四   | 17  |          3
(27 rows)

总结

row_number的排序是不稳定的,所以不会按照初始顺序进行输出,需要人为给定顺序。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。