Ano. S jednoduchou funkcí okna:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE /* whatever */
ORDER BY col1
OFFSET ?
LIMIT ?
Uvědomte si, že náklady budou podstatně vyšší než bez celkového počtu, ale obvykle stále levnější než dva samostatné dotazy. Postgres musí skutečně spočítat všechny řádky v obou směrech, což si vyžádá náklady v závislosti na celkovém počtu kvalifikujících řádků. Podrobnosti:
- Nejlepší způsob, jak získat počet výsledků před použitím LIMIT
Nicméně , jak zdůraznil Dani, když OFFSET
je alespoň tak velký jako počet řádků vrácených ze základního dotazu, nejsou vráceny žádné řádky. Takže také nezískáme full_count
.
Pokud to není přijatelné, je to možné řešení, jak vždy vrátit celý počet bude s CTE a 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;
Získáte jeden řádek hodnot NULL s full_count
připojeno, pokud OFFSET
je příliš velký. Jinak je připojen ke každému řádku jako v prvním dotazu.
Pokud je řádek se všemi hodnotami NULL možným platným výsledkem, musíte zaškrtnout offset >= full_count
k jednoznačnému určení původu prázdného řádku.
To stále provede základní dotaz pouze jednou. Ale přidává více režie k dotazu a platí pouze tehdy, pokud je to méně než opakování základního dotazu pro počet.
Pokud jsou k dispozici indexy podporující konečné pořadí řazení, může se vyplatit zahrnout ORDER BY
v CTE (redundantně).