Jak se vrátit na stránku výsledků z SQL?

hlasů
11

Mnoho aplikací mají mřížky, které zobrazují data z databáze tabulka jednu stránku najednou. Mnoho z nich také umožňují uživateli vybrat počet záznamů na stránku, třídit podle libovolného sloupce a pohybovat dopředu a dozadu přes výsledky.

Co je dobré algoritmus implementovat tento vzor aniž by to přineslo celou tabulku ke klientovi a pak filtrování dat na straně klienta. Jak se vám přinese jen ty záznamy, které chcete zobrazit uživateli?

Má LINQ zjednodušit řešení?

Položena 13/08/2008 v 19:38
zdroj uživatelem
V jiných jazycích...                            


8 odpovědí

hlasů
10

Na MS výše, SQL Server 2005 a ROW_NUMBER () Zdá se, že funguje:

T-SQL: Paging s ROW_NUMBER ()

DECLARE @PageNum AS INT;
DECLARE @PageSize AS INT;
SET @PageNum = 2;
SET @PageSize = 10;

WITH OrdersRN AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY OrderDate, OrderID) AS RowNum
          ,OrderID
          ,OrderDate
          ,CustomerID
          ,EmployeeID
      FROM dbo.Orders
)

SELECT * 
  FROM OrdersRN
 WHERE RowNum BETWEEN (@PageNum - 1) * @PageSize + 1 
                  AND @PageNum * @PageSize
 ORDER BY OrderDate
         ,OrderID;
Odpovězeno 13/08/2008 v 19:40
zdroj uživatelem

hlasů
7

Já bych doporučil buď pomocí LINQ, nebo se snaží kopírovat to, co dělá. Mám aplikaci, kde jsem použít LINQ Vezměte a Skip metody k načtení stránkovaného dat. Tento kód vypadá nějak takto:

MyDataContext db = new MyDataContext();
var results = db.Products
    .Skip((pageNumber - 1) * pageSize)
    .Take(pageSize);

Spuštěn SQL Server Profiler ukazuje, že LINQ je převod tohoto dotazu do SQL podobný:

SELECT [ProductId], [Name], [Cost], and so on...
FROM (
    SELECT [ProductId], [Name], [Cost], [ROW_NUMBER]
    FROM (
       SELECT ROW_NUMBER() OVER (ORDER BY [Name]) AS [ROW_NUMBER], 
           [ProductId], [Name], [Cost]
       FROM [Products]
    )
    WHERE [ROW_NUMBER] BETWEEN 10 AND 20
)
ORDER BY [ROW_NUMBER]

V jednoduché angličtině:
1. Filtrovat řádky a použijte funkci ROW_NUMBER přidat čísla řádků v pořadí, které chcete.
2. Filtr (1) vrátit pouze čísla řádků, které chcete na své stránce.
3. Druh (2) číslo řádku, což je stejné jako pořadí byste chtěli (v tomto případě, podle jména).

Odpovězeno 13/08/2008 v 20:29
zdroj uživatelem

hlasů
4

V zásadě existují dva způsoby stránkování v databázi (já jsem za předpokladu, že používáte SQL Server):

využitím posunutí

Jiní vysvětlil, jak ROW_NUMBER() OVER()je možné pořadí funkce slouží k provedení stránek. Za zmínku stojí, že SQL Server 2012 nakonec obsažená podporu standardu SQL OFFSET .. FETCHklauzule:

SELECT first_name, last_name, score
FROM players
ORDER BY score DESC
OFFSET 40 ROWS FETCH NEXT 10 ROWS ONLY

Pokud používáte SQL Server 2012 a zpětné kompatibility není problém, asi byste měli raději tuto klauzuli, protože bude proveden více optimálně SQL Server v rohových případech.

Použití metody SEEK

Tam je úplně jiná, mnohem rychlejší, ale méně známý způsob, jak provádět paging v SQL. To je často nazýván „hledají způsob“, jak je popsáno v tomto blogu zde .

SELECT TOP 10 first_name, last_name, score
FROM players
WHERE (score < @previousScore)
   OR (score = @previousScore AND player_id < @previousPlayerId)
ORDER BY score DESC, player_id DESC

@previousScoreA @previousPlayerIdhodnoty jsou příslušné hodnoty posledního záznamu z předchozí stránku. To vám umožní načíst stránku „Další“. V případě, že ORDER BYsměr ASC, jednoduše použít >místo.

S výše uvedeným způsobem, můžete okamžitě přejít na straně 4, aniž by nejprve přitažené za vlasy posledních 40 záznamů. Ale často, nechcete skočit tak daleko, tak jako tak. Místo toho dostanete mnohem rychlejší dotaz, který by mohl být schopen načíst data v konstantním čase, v závislosti na indexování. Plus, vaše stránky i nadále „stabilní“, bez ohledu na to, jestli se podkladová změny dat (například na straně 1, když jste na straně 4).

To je nejlepší způsob, jak implementovat stránkování když lazy loading více dat ve webových aplikacích, například.

Všimněte si, že „způsob se snaží“ se také nazývá sady klíčů paging .

Odpovězeno 26/10/2013 v 19:32
zdroj uživatelem

hlasů
3

LINQ v kombinaci s lambda výrazy a anonymních tříd .Net 3.5 obrovsky zjednodušuje tento druh věcí.

Dotazování databáze:

var customers = from c in db.customers
                join p in db.purchases on c.CustomerID equals p.CustomerID
                where p.purchases > 5
                select c;

Počet záznamů na stránce:

customers = customers.Skip(pageNum * pageSize).Take(pageSize);

Třídění podle libovolného sloupce:

customers = customers.OrderBy(c => c.LastName);

Získání pouze vybrané pole ze serveru:

var customers = from c in db.customers
                join p in db.purchases on c.CustomerID equals p.CustomerID
                where p.purchases > 5
                select new
                {
                    CustomerID = c.CustomerID,
                    FirstName = c.FirstName,
                    LastName = c.LastName
                };

To vytváří staticky zadali anonymní třídu, ve které si můžete přístup k jeho vlastnosti:

var firstCustomer = customer.First();
int id = firstCustomer.CustomerID;

Výsledky z dotazů jsou líní-naložený ve výchozím nastavení, takže se nemluví do databáze, dokud se skutečně potřebovat data. LINQ v .Net také výrazně zjednodušuje aktualizace udržováním DataContext veškeré změny, které jste provedli, a pouze aktualizovat pole, která vám změní.

Odpovězeno 15/08/2008 v 23:07
zdroj uživatelem

hlasů
1

Existuje několik řešení, které mohu použít s MS SQL 2005.

Jedním z nich je ROW_NUMBER (). Ale osobně nemám rád ROW_NUMBER (), protože to nefunguje pro velké výsledky (DB, který jsem pracovat na opravdu velký - více než 1 TB dat běží tisíce dotazů v druhý - víte - velký sociální sítě site).

Tady jsou moje oblíbené řešení.

Budu používat druh pseudo kód T-SQL.

Pojďme najít 2. strana uživatelů seřazených podle jménem, ​​příjmením, kde každá strana má 10 záznamů.

@page = 2 -- input parameter
@size = 10 -- can be optional input parameter

if @page < 1 then begin
    @page = 1 -- check page number
end
@start = (@page-1) * @size + 1 -- @page starts at record no @start

-- find the beginning of page @page
SELECT TOP (@start)
    @forename = forename,
    @surname = surname
    @id = id
FROM
    users
ORDER BY
    forename,
    surname,
    id -- to keep correct order in case of have two John Smith.

-- select @size records starting from @start
SELECT TOP (@size)
    id,
    forename,
    surname
FROM
    users
WHERE
    (forename = @forename and surname = @surname and id >= @id) -- the same name and surname, but bigger id
    OR (forename = @forename and surname > @surname) -- the same name, but bigger surname, id doesn't matter
    OR (forename > @forename) -- bigger forename, the rest doesn't matter
ORDER BY
    forename,
    surname,
    id
Odpovězeno 15/08/2008 v 22:44
zdroj uživatelem

hlasů
1

Oracle řešení:

select * from (
    select a.*, rownum rnum from (
        YOUR_QUERY_GOES_HERE -- including the order by
    ) a
    where rownum <= MAX_ROW
 ) where rnum >= MIN_ROW
Odpovězeno 13/08/2008 v 20:00
zdroj uživatelem

hlasů
1

Ve skutečnosti, LINQ má Skip a Take metody, které mohou být kombinovány vybrat záznamy, které jsou načteny.

Zkontrolovat ty ven.

Pro DB: stránkování v SQL Server 2005

Odpovězeno 13/08/2008 v 19:43
zdroj uživatelem

hlasů
0

Tam je diskuse o tom zde

Technika dostane číslo stránky 100,000 z databáze 150 tisíc řádku v 78ms

Použitím optimalizační znalosti a SET ROWCOUNT, první ČísloZaměstnance na stránce, která je požadována je uložen v lokální proměnné na výchozí bod. Dále SET ROWCOUNT na maximální počet záznamů, které jsou požadovány v @maximumRows. To umožňuje paging sadu výsledků v mnohem efektivnějším způsobem. Při použití této metody také využívá již existujících indexů na stole, protože jde přímo do základní tabulky, a ne lokálně vytvořené tabulky.

Obávám se, že nejsem schopen posoudit, jestli je lepší než aktuální přijímanou odpovědí.

Odpovězeno 11/09/2008 v 17:04
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more