2013-10-01 25 views
10

Mam ekran wyszukiwania, na którym użytkownik ma 5 filtrów do wyszukiwania.
Skonstruowałem zapytanie dynamiczne na podstawie tych wartości filtru i wyników na stronie 10 na raz.
to działa dobrze w SQL2012 przy użyciu OFFSET i FETCH, ale używam dwa zapytania, aby to zrobić.Uzyskaj całkowitą liczbę wierszy podczas przeglądania

Chcę pokazać 10 wyników i wyświetlić całkowitą liczbę wierszy znalezionych przez zapytanie (powiedzmy 1000).
Obecnie robię to, uruchamiając zapytanie: dwukrotnie - raz dla sumy całkowitej, a następnie ponownie dla strony 10 wierszy.
Czy jest to skuteczniejszy sposób?

Odpowiedz

19

Nie musisz dwukrotnie uruchamiać zapytania.

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

podstawie the chat, wydaje się, problem jest trochę bardziej skomplikowane - ubiegasz DISTINCT do wyniku oprócz stronicowania. Może to skomplikować, aby dokładnie określić, jak powinien wyglądać i jaki powinien być COUNT(). Oto jeden sposób (Chcę tylko wykazać to zamiast próby włączenia techniki w swoim znacznie bardziej złożonego zapytania z czatu):

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; 

Clean up:

DROP TABLE dbo.PagingSample; 
GO 
+0

Działa to tak, że w zapytaniu dynamicznym, jeśli podam nazwę zmiennej jako @oTotalRecords = COUNT (1) OVER(), oznacza to, że "Należy zadeklarować zmienną skalarną" @oTotalRecords ". Czy możesz mi powiedzieć, jak mogę – user788312

+0

Czytam wartość do zmiennej i odczytuję z niej w aplikacji – user788312

+0

Czy mogę pobrać ją do zmiennej z samego sql? – user788312

1

możesz spróbować coś takiego

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

lub

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 

Teraz masz całkowitą liczbę w kolumnie totalcnt i można korzystać z tej kolumny, aby wyświetlić całkowitą liczbę wierszy

+0

problemem jest to, że jest to odrębny tam, a więc utrudnia logiki bit.Na tym samym poziomie funkcja COUNT() OVER() zostanie obliczona przed DISTINCT. –

1

Mam nadzieję, że jestem nie jest za późno, aby wskoczyć w to pytanie, ale dziś wieczorem spotkałem się z bardzo podobnym problemem. Miałem klasę stronicowania, która zawyżała liczbę zwracanych wyników, ponieważ poprzedni programista rezygnował z DISTINCT i po prostu wykonał SELECT count (*) łączenia tabel. Chociaż to nie rozwiąże problemu 2 zapytania skończyło się za pomocą zagnieżdżonych kwerendę tak, że wyglądało to tak:

Original Zapytanie

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

zawyżone wyniki kwerendy

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

moje wyniki Rozwiązanie zapytania

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

Moje rozwiązanie jest podobne do "rs. Answer"

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; 

Wynik powrotu obejmie totalrow_count jak imię kolumnowej