Ja. Mit einer einfachen Fensterfunktion:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
Beachten Sie, dass die Kosten wesentlich höher sind als ohne die Gesamtzahl, aber in der Regel immer noch günstiger als zwei separate Abfragen. Postgres muss tatsächlich alle Zeilen in beide Richtungen zählen, was abhängig von der Gesamtzahl der qualifizierenden Zeilen Kosten verursacht. Einzelheiten:
Jedoch , wie Dani wies darauf hin , wenn OFFSET
mindestens so groß wie die Anzahl der Zeilen aus der Basis Abfrage zurückgegeben, werden keine Zeilen zurückgegeben. Also bekommen wir auch nicht full_count
.
Wenn dies nicht akzeptabel ist, besteht eine mögliche Problemumgehung, um immer die volle Anzahl zurückzugeben , in einem CTE und einem 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;
Sie erhalten eine Zeile mit NULL-Werten mit dem full_count
angehängten Wert, wenn dieser OFFSET
zu groß ist. Andernfalls wird es wie in der ersten Abfrage an jede Zeile angehängt.
Wenn eine Zeile mit allen NULL-Werten ein mögliches gültiges Ergebnis ist, müssen Sie überprüfen offset >= full_count
, ob der Ursprung der leeren Zeile eindeutig ist.
Dadurch wird die Basisabfrage immer noch nur einmal ausgeführt. Es erhöht jedoch den Overhead der Abfrage und zahlt sich nur aus, wenn dies weniger ist als das Wiederholen der Basisabfrage für die Zählung.
Wenn Indizes verfügbar sind, die die endgültige Sortierreihenfolge unterstützen, kann es sich lohnen, die ORDER BY
in den CTE aufzunehmen (redundant).