Да. С простой оконной функцией:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
Имейте в виду, что стоимость будет значительно выше, чем без общего числа, но обычно все же дешевле, чем два отдельных запроса. Postgres должен фактически подсчитывать все строки в любом случае, что требует затрат в зависимости от общего количества подходящих строк. Детали:
Однако , как указала Дэни , когда OFFSET
количество строк, по крайней мере , равно количеству строк, возвращаемых из базового запроса, строки не возвращаются. Так что мы тоже не получаем full_count
.
Если это неприемлемо, возможный обходной путь, чтобы всегда возвращать полный счет, был бы с CTE и 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;
Вы получаете одну строку значений NULL с full_count
добавлением, если OFFSET
оно слишком велико. В противном случае он добавляется к каждой строке, как в первом запросе.
Если строка со всеми значениями NULL является возможным допустимым результатом, вы должны проверить, offset >= full_count
чтобы устранить неоднозначность происхождения пустой строки.
Это по-прежнему выполняет базовый запрос только один раз. Но он увеличивает накладные расходы на запрос и платит, только если это меньше, чем повторение базового запроса для подсчета.
Если доступны индексы, поддерживающие окончательный порядок сортировки, может быть полезно включить ORDER BY
в CTE (избыточно).