Tak. Z prostą funkcją okna:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE /* whatever */
ORDER BY col1
OFFSET ?
LIMIT ?
Należy pamiętać, że koszt będzie znacznie wyższy niż bez łącznej liczby, ale zazwyczaj nadal będzie tańszy niż dwa oddzielne zapytania. Postgres musi właściwie policzyć wszystkie wiersze tak czy inaczej, co nakłada koszt w zależności od łącznej liczby kwalifikujących się wierszy. Szczegóły:
- Najlepszy sposób na uzyskanie liczby wyników przed zastosowaniem LIMITu
Jednak , jak zauważyła Dani, kiedy OFFSET
jest co najmniej tak duża, jak liczba wierszy zwróconych z zapytania podstawowego, żadne wiersze nie są zwracane. Dlatego też nie otrzymujemy full_count
.
Jeśli jest to nie do przyjęcia, możliwe obejście, aby zawsze zwracać pełną liczbę będzie z CTE i 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;
Otrzymasz jeden wiersz wartości NULL z full_count
dołączany, jeśli OFFSET
jest za duży. W przeciwnym razie jest dodawany do każdego wiersza, tak jak w pierwszym zapytaniu.
Jeśli wiersz ze wszystkimi wartościami NULL jest możliwym prawidłowym wynikiem, musisz sprawdzić offset >= full_count
aby odróżnić pochodzenie pustego wiersza.
To nadal wykonuje zapytanie podstawowe tylko raz. Ale zwiększa to obciążenie zapytania i płaci tylko wtedy, gdy jest to mniej niż powtórzenie zapytania podstawowego dla licznika.
Jeśli indeksy obsługujące ostateczną kolejność sortowania są dostępne, może być opłacalne dołączenie ORDER BY
w CTE (nadmiarowo).