在讲FETCH FIRST WITH TIES之前我们先来看下PG怎么分页?
语法一:
LIMIT { count | ALL }
OFFSET start
语法二:
OFFSET start { ROW | ROWS }
FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY
postgres=# CREATE TABLE test(name varchar(64),score int2);
CREATE TABLE
postgres=# INSERT INTO test(name, score) VALUES('张三','100'),('李四','90'),('王五1','80'),('王五2','80'),('王五3','80');
INSERT 0 5
postgres=# SELECT * FROM test;
name | score
-------+-------
张三 | 100
李四 | 90
王五1 | 80
王五2 | 80
王五3 | 80
(5 rows)
--这个是我们常用的分页方式,LIMIT控制返回的行数,OFFSET控制起始行
postgres=# SELECT *
postgres-# FROM test
postgres-# ORDER BY score DESC
postgres-# LIMIT 2 OFFSET 0;
name | score
------+-------
张三 | 100
李四 | 90
(2 rows)
--这个是SQL:2008中的语法,实现了一样的功能
--FIRST和NEXT等价,ROW和ROWS等价,OFFSET控制起始行,FETCH { FIRST | NEXT } 控制返回的行数
postgres=# SELECT *
postgres-# FROM test
postgres-# ORDER BY score DESC
postgres-# OFFSET 0
postgres-# FETCH FIRST 2 ROWS ONLY;
name | score
------+-------
张三 | 100
李四 | 90
(2 rows)
复制
如果SQL:2008中定义的语法和以前完全一样就没有必要新增语法了,其实只是PG实现不完全而已,在PG13又实现了一部分新功能,语法如下:
OFFSET start { ROW | ROWS }
FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } { ONLY | WITH TIES }
WITH TIES就是为了解决排名相同的问题,先看实例
--这里FETCH FIRST为3,按照以前的语法应该是返回3条数据,但是这里却返回了5条数据
--WITH TIES 选项表示返回排名和最后一行相同的额外数据行,而且必须同时指定 ORDER BY 子句
--因为第三行80分的有3条数据,所以就全部返回
--这里就解决了一页中的最后一行相同的数据在同一页展现的问题
postgres=# SELECT *
postgres-# FROM test
postgres-# ORDER BY score DESC
postgres-# OFFSET 0
postgres-# FETCH FIRST 3 ROWS WITH TIES;
name | score
-------+-------
张三 | 100
李四 | 90
王五1 | 80
王五2 | 80
王五3 | 80
(5 rows)
复制
在使用新语法新功能是也有一些注意事项:
--在使用WITH TIES 选项时必须指定 ORDER BY 子句,否则将会返回错误
postgres=# SELECT *
postgres-# FROM test
postgres-# FETCH FIRST 3 ROWS WITH TIES;
ERROR: WITH TIES cannot be specified without ORDER BY clause
--分页中的起始行不再固定,因为前一页中的的最后一行有可能有排名相同的数据
postgres=# INSERT INTO test VALUES('王麻子','60');
INSERT 0 1
postgres=# SELECT * FROM test;
name | score
--------+-------
张三 | 100
李四 | 90
王五1 | 80
王五2 | 80
王五3 | 80
王麻子 | 60
(6 rows)
--虽然指定了count为3,但实际返回了5行数据。如果我们基于这个功能实现分页查询,
--需要记录每次实际返回的行数;对应上面的示例,第一页返回5行数据,查询第二页时的语句如下:
postgres=# SELECT *
postgres-# FROM test
postgres-# ORDER BY score DESC
postgres-# OFFSET 5
postgres-# FETCH FIRST 3 ROWS WITH TIES;
name | score
--------+-------
王麻子 | 60
(1 row)
--WITH TIES是严格按照ORDER BY进行排序的,但是这里有个问题,例如我需要实现先按分数倒序排名,然后再按姓名进行排序,我们先把name的字段直接放入ORDER BY看看效果
postgres=# SELECT *
postgres-# FROM test
postgres-# ORDER BY score DESC,name
postgres-# OFFSET 0
postgres-# FETCH FIRST 3 ROWS WITH TIES;
name | score
-------+-------
张三 | 100
李四 | 90
王五1 | 80
(3 rows)
--以上结果并非我们想要的,我们需要的是第一页把为80分的全部返回,分数相同按姓名排序,
--但是这里少了数据,由于我们以上的写法排序是按照score和name排序,那么第三行并没有相同的排名了
--如果我们要实现以上需求可以使用通用表表达式或子查询
postgres=# SELECT *
postgres-# FROM (SELECT *
postgres(# FROM test
postgres(# ORDER BY score DESC
postgres(# OFFSET 0
postgres(# FETCH FIRST 3 ROWS WITH TIES) t
postgres-# ORDER BY score DESC,name;
name | score
-------+-------
张三 | 100
李四 | 90
王五1 | 80
王五2 | 80
王五3 | 80
(5 rows)
postgres=# WITH tmp_sort AS (SELECT *
postgres(# FROM test
postgres(# ORDER BY score DESC
postgres(# OFFSET 0
postgres(# FETCH FIRST 3 ROWS WITH TIES)
postgres-# SELECT * FROM tmp_sort ORDER BY score DESC,name;
name | score
-------+-------
张三 | 100
李四 | 90
王五1 | 80
王五2 | 80
王五3 | 80
(5 rows)
复制
最后修改时间:2021-02-24 11:46:54
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
PostgreSQL13新特性FETCH FIRST WITH TIES
3月前

评论
相关阅读
玩一玩系列——玩玩pg_mooncake(PostgreSQL的高性能列存新贵)
小满未满、
527次阅读
2025-03-03 17:18:03
王炸!OGG 23ai 终于支持从PostgreSQL备库抽取数据了
曹海峰
398次阅读
2025-03-09 12:54:06
玩一玩系列——玩玩login_hook(一款即将停止维护的PostgreSQL登录插件)
小满未满、
374次阅读
2025-03-08 18:19:28
明明想执行的SQL是DELETE、UPDATE,但为什么看到的是SELECT(FDW的实现原理解析)
小满未满、
350次阅读
2025-03-19 23:11:26
PostgreSQL初/中/高级认证考试(3.15)通过考生公示
开源软件联盟PostgreSQL分会
302次阅读
2025-03-20 09:50:36
IvorySQL 4.4 发布 - 基于 PostgreSQL 17.4,增强平台支持
通讯员
195次阅读
2025-03-20 15:31:04
套壳论
梧桐
187次阅读
2025-03-09 10:58:17
命名不规范,事后泪两行
xiongcc
176次阅读
2025-03-13 14:26:08
版本发布| IvorySQL 4.4 发布
IvorySQL开源数据库社区
114次阅读
2025-03-13 09:52:33
PG vs MySQL 执行计划解读的异同点
进击的CJR
114次阅读
2025-03-21 10:50:08