PostgreSQL 排序字段不唯一导致分页查询结果出现重复数据

这里写目录标题

  • 复现步骤
    • 查询第一页
    • 查询第二页
  • 解决方式
  • 预防

复现步骤

create table test_select_order_page_duplicate
(
	id varchar(36) not null
		constraint test_select_order_page_duplicate_pk
			primary key,
	name varchar,
	age integer
);

alter table test_select_order_page_duplicate owner to postgres;


insert
into test_select_order_page_duplicate
    ( id, name, age )
values
    ( '1111', 'aa', 12 ),
    ( '2222', 'aa', 12 ),
    ( '3333', 'aa', 12 ),
    ( '4444', 'aa', 12 ),
    ( '5555', 'aa', 13 ),
    ( '6666', 'aa', 12 ),
    ( '7777', 'aa', 12 ),
    ( '8888', 'aa', 13 ),
    ( '9999', 'aa', 12 ),
    ( '10101010', 'aa', 12 ),
    ( '11111111', 'aa', 14 ),
    ( '12121212', 'aa', 14 ),
    ( '13131313', 'aa', 12 );

查询第一页

select *
from
    test_select_order_page_duplicate tsopd
order by
    tsopd.age
limit 3;
id name age
2222 aa 12
3333 aa 12
1111 aa 12

查询第二页

select *
from
    test_select_order_page_duplicate tsopd
order by
    tsopd.age
limit 3 offset 3;
id name age
2222 aa 12
6666 aa 12
7777 aa 12

可以明显看到,两次分页查询出现了同一条id为2222的记录,但实际上数据库里只有一条2222,查询结果莫名出现了重复数据。

解决方式

核心思路就是让order by拥有唯一性。

具体解决方式就是,补充一个有唯一约束或者大概率唯一的字段作为次级排序条件。

例如,补充主键作为排序条件:

select *
from
    test_select_order_page_duplicate tsopd
order by
    tsopd.age, tsopd.id desc

预防

n对1关系的连表查询时,如果根据1端表的字段排序就肯定要加一个n端的id

你可能感兴趣的:(PostgreSQL,sql,postgresql)