Ja. Med en simpel vinduesfunktion:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE /* whatever */
ORDER BY col1
OFFSET ?
LIMIT ?
Vær opmærksom på, at prisen vil være væsentligt højere end uden det samlede antal, men typisk stadig billigere end to separate forespørgsler. Postgres skal faktisk tælle alle rækker begge veje, hvilket pålægger en omkostning afhængig af det samlede antal kvalificerende rækker. Detaljer:
- Bedste måde at få resultattælling, før LIMIT blev anvendt
Men , som Dani påpegede, da OFFSET
er mindst lige så stort som antallet af rækker, der returneres fra basisforespørgslen, returneres ingen rækker. Så vi får heller ikke full_count
.
Hvis det ikke er acceptabelt, er en mulig løsning for altid at returnere det fulde antal ville være med en CTE og en 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;
Du får en række NULL-værdier med full_count
tilføjet hvis OFFSET
er for stor. Ellers er den tilføjet til hver række som i den første forespørgsel.
Hvis en række med alle NULL-værdier er et muligt gyldigt resultat, skal du kontrollere offset >= full_count
for at tvetydige oprindelsen af den tomme række.
Dette udfører stadig kun basisforespørgslen én gang. Men det føjer mere overhead til forespørgslen og betaler kun, hvis det er mindre end at gentage basisforespørgslen for optællingen.
Hvis indekser, der understøtter den endelige sorteringsrækkefølge, er tilgængelige, kan det betale sig at inkludere ORDER BY
i CTE (redundant).