Sì. Con una semplice funzione finestra:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
Tieni presente che il costo sarà notevolmente superiore rispetto a quello senza il numero totale, ma in genere ancora più economico di due query separate. Postgres deve effettivamente contare tutte le righe in entrambi i modi, il che impone un costo in base al numero totale di righe qualificate. Dettagli:
Tuttavia , come ha sottolineato Dani , quando OFFSET
è grande almeno quanto il numero di righe restituite dalla query di base, non viene restituita alcuna riga. Quindi anche noi non otteniamo full_count
.
Se ciò non è accettabile, una possibile soluzione alternativa per restituire sempre il conteggio completo sarebbe con un CTE e un 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;
Ottieni una riga di valori NULL con l' full_count
aggiunta se OFFSET
è troppo grande. Altrimenti, viene aggiunto a ogni riga come nella prima query.
Se una riga con tutti i valori NULL è un possibile risultato valido, è necessario verificare offset >= full_count
per disambiguare l'origine della riga vuota.
Ciò esegue ancora la query di base solo una volta. Ma aggiunge più overhead alla query e paga solo se è inferiore alla ripetizione della query di base per il conteggio.
Se sono disponibili indici che supportano l'ordinamento finale, potrebbe essere conveniente includerli ORDER BY
nella CTE (in modo ridondante).