Postgres - 按物质排序的位置?

时间:2013-09-18 11:36:04

标签: sql postgresql limit offset

嗨我有一个包含实体的表,id是从序列生成的

我的表中有超过2个条目,现在我想浏览所有元素。但

LIMIT 100 OFFSET 2000000

对我来说太慢了,所以我尝试了两种不同的语句(伪代码)

int i = 0;    
while(true) {
    a: SELECT * FROM entity WHERE id>=i ORDER BY id LIMIT 100 
    b: SELECT * FROM (SELECT * FROM entity ORDER BY id)a WHERE id>=i  LIMIT 100 
    i=<id of last fetched row>;
}

两个查询都很快,似乎显示出正确的结果......但我有一种预感,一个不会总是有效...任何想法?我需要订购吗?

1 个答案:

答案 0 :(得分:0)

order by 的查询位置确实无关紧要。 AFAIK,在SQL规范中,如果您未在最外层查询中指定order by,则根本无法保证结果集中的行顺序。有时候你可以按照自己的意愿订购行,但不能保证。

要显示它,这是一个小测试 - 假设我们有这样的表test

create table test(id int, name text);

insert into test 
select 1, 'John' union all
select 2, 'Adele';

现在让我们运行一些查询。这个工作正常(由order by保证):

select * from test as t1 order by t1.name;

id    name
-----------
2     Adele
1     John

这个工作正常几乎可以肯定,它是从有序子查询中选择的,SQL没有理由重新排序:

select * from (select * from test order by name) as t1

id    name
-----------
2     Adele
1     John

但是假设我们必须在此查询中使用自联接。这个也将正常工作(由order by保证):

select *
from test as t1
    inner join test as t2 on t2.id = t1.id
order by t1.name;

id    name
-----------
2     Adele
1     John

但由于merge join,这个会被重新排序。 SQL必须在合并连接期间按连接列对集合进行排序,以便重新排序t1,并且由于您未指定外部order by,因此将返回id排序的结果:

select *
from (select * from test order by name) as t1
    inner join test as t2 on t2.id = t1.id;

id    name
-----------
1     John
2     Adele

<强> sql fiddle demo

对于原始问题,如果您的选择之间发生了一些数据修改,即使在最外层查询中指定order by也无效。