Так. За допомогою простої функції вікна:
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 (зайве).