44

我注意到分页记录集中有一些重复的行。

当我运行此查询时:

SELECT "students".* 
FROM "students" 
ORDER BY "students"."status" asc 
LIMIT 3 OFFSET 0

我得到:

    | id | name  | status |
    | 1  | foo   | active |
    | 12 | alice | active |
    | 4  | bob   | active |

下一个查询:

SELECT "students".* 
FROM "students" 
ORDER BY "students"."status" asc 
LIMIT 3 OFFSET 3

我得到:

    | id | name  | status |
    | 1  | foo   | active |
    | 6  | cindy | active |
    | 2  | dylan | active |

为什么“foo”出现在两个查询中?

4

3 回答 3

75

为什么“foo”出现在两个查询中?

因为返回的所有行都具有相同的status列值。在这种情况下,数据库可以自由地以它想要的任何顺序返回行。

如果您想要可重现的排序,则需要在 order by 语句中添加第二列以使其一致。例如 ID 列:

SELECT students.* 
FROM students 
ORDER BY students.status asc, 
         students.id asc

如果两行的状态列具有相同的值,它们将按 id 排序。

于 2012-11-27T09:19:38.527 回答
25

有关 PostgreSQL 文档 ( http://www.postgresql.org/docs/8.3/static/queries-limit.html ) 的更多详细信息:

使用 LIMIT 时,使用 ORDER BY 子句将结果行约束为唯一顺序很重要。否则,您将获得查询行的不可预测的子集。您可能要求第 10 到第 20 行,但第 10 到第 20 行的顺序是什么?排序是未知的,除非您指定了 ORDER BY。

查询优化器在生成查询计划时会考虑 LIMIT,因此根据您为 LIMIT 和 OFFSET 提供的内容,您很可能会获得不同的计划(产生不同的行顺序)。因此,使用不同的 LIMIT/OFFSET 值来选择查询结果的不同子集将产生不一致的结果,除非您使用 ORDER BY 强制执行可预测的结果排序。这不是错误;这是 SQL 不承诺以任何特定顺序提供查询结果的事实的固有结果,除非使用 ORDER BY 来约束顺序。

于 2015-06-11T09:13:57.517 回答
0
select * from(
    Select "students".* 
    from "students" 
    order by "students"."status" asc 
    limit 6
) as temp limit 3 offset 0;
select * from(
    Select "students".* 
    from "students" 
    order by "students"."status" asc 
    limit 6
) as temp limit 3 offset 3;

其中 6 是正在检查的记录总数。

于 2021-07-29T08:40:13.767 回答