Sim. Com uma função de janela simples:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
Esteja ciente de que o custo será substancialmente maior do que sem o número total, mas normalmente ainda mais barato do que duas consultas separadas. O Postgres tem que contar todas as linhas de qualquer maneira, o que impõe um custo dependendo do número total de linhas qualificadas. Detalhes:
No entanto , como Dani apontou , quando OFFSETé pelo menos tão grande quanto o número de linhas retornadas da consulta base, nenhuma linha é retornada. Então também não entendemos full_count.
Se isso não for aceitável, uma possível solução alternativa para sempre retornar a contagem completa seria com um CTE e um 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;
Você obtém uma linha de valores NULL com o full_countanexado se OFFSETfor muito grande. Caso contrário, é anexado a todas as linhas, como na primeira consulta.
Se uma linha com todos os valores NULL for um resultado válido possível, você deve verificar offset >= full_countpara desambiguar a origem da linha vazia.
Isso ainda executa a consulta de base apenas uma vez. Mas adiciona mais sobrecarga à consulta e só paga se isso for menor do que repetir a consulta de base para a contagem.
Se os índices que suportam a ordem de classificação final estiverem disponíveis, pode valer a pena incluir o ORDER BYno CTE (redundantemente).