Tak. Dzięki prostej funkcji okna:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
Należy pamiętać, że koszt będzie znacznie wyższy niż bez całkowitej liczby, ale zazwyczaj nadal będzie tańszy niż dwa oddzielne zapytania. Postgres musi faktycznie policzyć wszystkie wiersze w obie strony, co narzuca koszt w zależności od całkowitej liczby kwalifikujących się wierszy. Detale:
Jednak , jak zauważył Dani , gdy OFFSET
jest co najmniej tak duża, jak liczba wierszy zwróconych z zapytania podstawowego, żadne wiersze nie są zwracane. Więc my też nie dostajemy full_count
.
Jeśli to nie do zaakceptowania, możliwym obejściem, aby zawsze zwracać pełną liczbę, byłoby użycie CTE i 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;
Otrzymasz jeden wiersz wartości NULL z full_count
dołączonym jeśli OFFSET
jest za duży. W przeciwnym razie jest dołączany do każdego wiersza, tak jak w pierwszym zapytaniu.
Jeśli wiersz zawierający wszystkie wartości NULL jest możliwym prawidłowym wynikiem, należy sprawdzić, offset >= full_count
aby ujednoznacznić pochodzenie pustego wiersza.
To nadal wykonuje zapytanie podstawowe tylko raz. Ale dodaje więcej narzutu do zapytania i płaci tylko wtedy, gdy to mniej niż powtórzenie zapytania podstawowego dla liczby.
Jeśli dostępne są indeksy obsługujące ostateczny porządek sortowania, może się opłacić uwzględnienie ORDER BY
w CTE (nadmiarowo).