web-dev-qa-db-ja.com

PostgreSQL-LIMITOFFSETから行を繰り返す

ページ付けされたレコードセットにいくつかの繰り返し行があることに気づきました。

このクエリを実行すると:

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」が表示されるのはなぜですか?

30
keewooi

両方のクエリに「foo」が表示されるのはなぜですか?

返されるすべての行のstatus列の値が同じであるためです。その場合、データベースは自由に行を任意の順序で返すことができます。

再現可能な注文が必要な場合は、一貫性を保つために、orderbyステートメントに2番目の列を追加する必要があります。例えば。 ID列:

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

2つの行のステータス列の値が同じである場合、それらはIDでソートされます。

40

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で予測可能な結果の順序付けを強制しない限り、一貫性のない結果が得られます。 これはバグではありません。これは、ORDER BYを使用して順序を制約しない限り、SQLがクエリの結果を特定の順序で配信することを約束しないという事実の本質的な結果です。

15
Ahmed MANSOUR