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