はい。単純なウィンドウ関数を使用すると:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
コストは総数がない場合よりも大幅に高くなりますが、通常は2つの個別のクエリよりも安価であることに注意してください。Postgresは実際にはいずれかの方法ですべての行をカウントする必要があり、これには対象となる行の総数に応じてコストがかかります。詳細:
ただし、Daniが指摘したように、OFFSET
少なくとも基本クエリから返される行数と同じ数の場合、行は返されません。したがって、も取得できませんfull_count
。
それが受け入れられない場合、常にフルカウントを返すための可能な回避策は、CTEとOUTER JOIN
:を使用することです。
WITH cte AS (
SELECT *
FROM tbl
WHERE
)
SELECT *
FROM (
TABLE cte
ORDER BY col1
LIMIT ?
OFFSET ?
) sub
RIGHT JOIN (SELECT count(*) FROM cte) c(full_count) ON true;
が大きすぎるfull_count
場合OFFSET
は、NULL値が1行追加されます。それ以外の場合は、最初のクエリと同様にすべての行に追加されます。
すべてNULL値の行が有効な結果である可能性がある場合offset >= full_count
は、空の行の起点を明確にするためにチェックする必要があります。
これでも、基本クエリは1回だけ実行されます。ただし、クエリにオーバーヘッドが追加され、カウントの基本クエリを繰り返すよりも少ない場合にのみ支払いが行われます。
最終的なソート順をサポートするインデックスが利用可能な場合ORDER BY
は、CTEに(冗長に)含めることで料金が発生する可能性があります。