Sì. Con una semplice funzione finestra:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE /* whatever */
ORDER BY col1
OFFSET ?
LIMIT ?
Tieni presente che il costo sarà sostanzialmente superiore rispetto a quello senza il numero totale, ma in genere sarà comunque più economico di due query separate. Postgres deve effettivamente contare tutte le righe in entrambi i casi, il che impone un costo che dipende dal numero totale di righe qualificanti. Dettagli:
- Il modo migliore per ottenere il conteggio dei risultati prima dell'applicazione del LIMIT
Tuttavia , come ha sottolineato Dani, quando OFFSET
è almeno pari al numero di righe restituite dalla query di base, non vengono restituite righe. Quindi non otteniamo nemmeno 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 /* whatever */
)
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 full_count
aggiunto 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 devi controllare offset >= full_count
per chiarire l'origine della riga vuota.
Questo esegue ancora la query di base solo una volta. Ma aggiunge più sovraccarico 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 utile includere ORDER BY
nel CTE (ridondante).