2013-10-01 7 views
10

У меня есть экран поиска, в котором пользователь имеет 5 фильтров для поиска.
Я построил динамический запрос, основанный на этих значениях фильтра, и на страницах 10 результатов за раз.
Это работает отлично в SQL2012 с помощью OFFSET и FETCH, но я использую два запросы, чтобы сделать это.Получить общее количество строк во время подкачки

Я хочу показать 10 результатов и показать общее количество строк, найденных по запросу (скажем 1000).
В настоящее время я делаю это, запустив запрос дважды - один раз для общего счета, затем снова на страницу 10 строк.
Есть ли более эффективный способ сделать это?

ответ

19

Вам не нужно дважды запускать запрос.

SELECT ..., total_count = COUNT(*) OVER() 
FROM ... 
ORDER BY ... 
OFFSET 120 ROWS 
FETCH NEXT 10 ROWS ONLY; 

на основе the chat, кажется, ваша проблема немного сложнее - вы подаете DISTINCT в результате в дополнение к пейджинга. Это может усложнить определение того, как должен выглядеть COUNT() и куда он должен идти. Вот один из способов (я просто хочу, чтобы это продемонстрировать, а не пытаться включать технику в свой гораздо более сложный запрос из чата):

USE tempdb; 
GO 
CREATE TABLE dbo.PagingSample(id INT,name SYSNAME); 

-- insert 20 rows, 10 x 2 duplicates 
INSERT dbo.PagingSample SELECT TOP (10) [object_id], name FROM sys.all_columns; 
INSERT dbo.PagingSample SELECT TOP (10) [object_id], name FROM sys.all_columns; 

SELECT COUNT(*) FROM dbo.PagingSample; -- 20 

SELECT COUNT(*) FROM (SELECT DISTINCT id, name FROM dbo.PagingSample) AS x; -- 10 

SELECT DISTINCT id, name FROM dbo.PagingSample; -- 10 rows 

SELECT DISTINCT id, name, COUNT(*) OVER() -- 20 (DISTINCT is not computed yet) 
FROM dbo.PagingSample 
ORDER BY id, name 
OFFSET (0) ROWS FETCH NEXT (5) ROWS ONLY; -- 5 rows 

-- this returns 5 rows but shows the pre- and post-distinct counts: 
SELECT PostDistinctCount = COUNT(*) OVER() -- 10, 
    PreDistinctCount -- 20, 
    id, name 
FROM 
(
    SELECT DISTINCT id, name, PreDistinctCount = COUNT(*) OVER() 
    FROM dbo.PagingSample 
    -- INNER JOIN ... 
) AS x 
ORDER BY id, name 
OFFSET (0) ROWS FETCH NEXT (5) ROWS ONLY; 

ВЫМЫТЬ:

DROP TABLE dbo.PagingSample; 
GO 
+0

Это работает именно так, что в динамическом запросе, если я даю имя переменной @oTotalRecords = COUNT (1) OVER(), он говорит, что «Должен объявить скалярную переменную @oTotalRecords». Не могли бы вы рассказать мне, как я могу исправьте это. – user788312

+0

Я читаю значение в переменной и читаю из этого в приложении. – user788312

+0

Могу ли я получить его в переменной из самого sql? – user788312

1

Вы можете попробовать что-то вроде этого

SELECT TOP 10 * FROM 
(
    SELECT COUNT(*) OVER() TOTALCNT, T.* 
    FROM TABLE1 T 
    WHERE col1 = 'somefilter' 
) v 

или

SELECT * FROM 
(
    SELECT COUNT(*) OVER() TOTALCNT, T.* 
    FROM TABLE1 T 
    WHERE col1 = 'somefilter' 
) v 
ORDER BY COL1 
OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY 

Теперь у вас есть общее количество в столбце totalcnt и вы можете использовать этот столбец, чтобы показать общее количество строк

+0

Проблема в том, существует отчетливый там, так что усложняет логику немного.На том же уровне COUNT() OVER() будет рассчитан до DISTINCT. –

1

Я надеюсь, что я не слишком поздно вникать в этот вопрос, но сегодня я столкнулся с очень похожими проблемами. У меня был класс подкачки, который превысил количество возвращаемых результатов, потому что предыдущий разработчик удалял DISTINCT и просто выполнял подсчет SELECT (*) в таблице. Хотя это не решает проблему 2 запроса я в конечном итоге с помощью вложенного запроса так, чтобы он выглядел следующим образом:

Оригинал Запрос

SELECT DISTINCT 
    field1, field2 
FROM 
    table1 t1 
    left join table2 t2 on t2.id = t1.id 

За надутых Результаты запроса

SELECT 
    count(*) 
FROM 
    table1 t1 
    left join table2 t2 on t2.id = t1.id 

Мои результаты Запрос решения

SELECT 
    count(*) 
FROM 
    (SELECT DISTINCT 
    field1, field2 
    FROM 
    table1 t1 
    left join table2 t2 on t2.id = t1.id) as tbl; 
2

Мое решение похоже на «Ответы на вопросы»

DECLARE @PageNumber AS INT, @RowspPage AS INT 
SET @PageNumber = 2 
SET @RowspPage = 5 

SELECT COUNT(*) OVER() totalrow_count,* 
    FROM databasename 
    where columnname like '%abc%' 
    ORDER BY columnname 
    OFFSET ((@PageNumber - 1) * @RowspPage) ROWS 
    FETCH NEXT @RowspPage ROWS ONLY; 

Возвращаемый результат будет включать в себя totalrow_count в качестве имени столбца

Смежные вопросы