Frage

Was wäre der effizienteste Weg, um eine Paging-Abfrage in SQL Server 2000?

zu tun

Wenn eine "Paging-Abfrage" das äquivalent mit der LIMIT-Anweisung in MySQL sei.

EDIT: Könnte eine gespeicherte Prozedur ist effizienter als jeder Satz Abfrage in diesem Fall

War es hilfreich?

Lösung

Paging von großem Result und der Gewinner RowCount verwendet. Auch gibt es eine verallgemeinerte Version für komplexere Abfragen. Aber geben Kredite an Jasmin Muharemovic :)

DECLARE @Sort /* the type of the sorting column */
SET ROWCOUNT @StartRow
SELECT @Sort = SortColumn FROM Table ORDER BY SortColumn
SET ROWCOUNT @PageSize
SELECT ... FROM Table WHERE SortColumn >= @Sort ORDER BY SortColumn

Der Artikel enthält den gesamten Quellcode.

Bitte lesen Sie die "Update 2004-05-05" -Informationen. !

Andere Tipps

Ich denke, eine verschachtelte SELECT TOP n Abfrage ist wahrscheinlich der effizienteste Weg, um es zu erreichen.

SELECT TOP ThisPageRecordCount *
FROM Table
WHERE ID NOT IN (SELECT TOP BeforeThisPageRecordCount ID FROM Table ORDER BY OrderingColumn)
ORDER BY OrderingColumn

Ersetzen ThisPageRecordCount mit Artikel pro Seite und BeforeThisPageRecordCount mit (PageNumber - 1) * items-per-page.

Natürlich ist der bessere Weg in SQL Server 2005 ist die ROW_NUMBER() Funktion in einem WAK zu verwenden.

Die Effizienz der Abfrage hängt wirklich davon ab, wie die zugrunde liegende Tabelle strukturiert ist. Wenn, sagen wir haben Sie einen Primärschlüssel-ID genannt, die eine Identität ist, und es ist ein Clustered-Index, und können Sie davon ausgehen, dass niemand wurde IDENTITY_INSERTs auf, es zu tun, können Sie tun eine Abfrage wie:

SELECT TOP XXX FROM Tabelle WHERE ID> @LastPagesID;

Das wird Ihnen Ergebnisse so schnell wie möglich bekommen. Alles andere, was wirklich effizient ist eine Variante zu diesem Thema sein wird - vielleicht ist es nicht eine ID - vielleicht was Sie verwenden Seite ist eigentlich ein Datum, das Sie wissen, einzigartig zu sein, aber Sie erhalten den Punkt ... Der IN () basiert hier wahrscheinlich gezeigt Abfragen arbeiten, aber sie werden die Leistung eines Teil gruppierten oder Abdeckung Index-Scan nicht berühren.

Ich denke, was Sie wirklich hier haben ein zwingender Grund zu der SQL 2005 zu aktualisieren.

In SQL 2005 diese schnell durchgeführt werden kann und einfach mit:

select ROW_NUMBER() over (order by [MyField]) as rowNum, *
from [MyTable]
where rowNum between @firstRow and @lastRow

Wenn Sie wirklich mit SQL 2000 stecken ich Sorge hatte -. Microsoft werden nicht voll es viel mehr gegeben unterstützen, dass es jetzt wieder zwei Generationen ist

Es wird nicht gehen am besten Weg, dies ich habe Angst zu tun - alle Lösungen sind irgendwie hackt

.

@Petar Petrov Antwort ist wahrscheinlich die konsequenteste jedoch:

  • Wenn Sie mit einem Clustered-Index auf einem kleineren Tisch zu tun haben für Ihre Art dann der ASC-DESC-Methode (dynamisch Bau von zwei Sorten jede Art und Weise unter Verwendung von TOP) ist wahrscheinlich schneller.
  • Wenn Ihre Daten relativ statisch sind und Ihre Art festgelegt ist, dann können Sie Ihr eigenes rowNum Feld hinzufügen, die Sie aktualisieren, wenn Sie die Sortierreihenfolge ändern (klingt schrecklich, aber für große Tabellen schnell sein).

Ich glaube, Sie in ein paar Stunden freuen jedesmal mit Query Analyzer zwicken. Eine gespeicherte Prozedur wird nicht viel Unterschied entweder Weg machen -. Das Caching des Abfrageplans ist nicht wahrscheinlich, den Engpass sein

Dies ist eine generische SQL Server 2000 gespeicherte Prozedur, die Paginierung auf einer Tabelle durchführen wird. Die gespeicherte Prozedur akzeptiert den Namen der Tabelle, die Spalten zur Ausgabe (Standard: alle Spalten in der Tabelle), eine optionale WHERE-Bedingung, eine optionale Sortierreihenfolge, die Seitennummer abzurufen, und die Anzahl der Zeilen pro Seite.

    CREATE PROCEDURE [dbo].[GetPage]
    @pTableName VARCHAR(30),
    @pColumns VARCHAR(200) = '*',
    @pFilter VARCHAR(200) = '',
    @pSort VARCHAR(200) = '',
    @pPage INT = 1,
    @pPageRows INT = 10
    AS

    SET NOCOUNT ON
    DECLARE @vSQL VARCHAR(4000)
    DECLARE @vTempTable VARCHAR(30)
    DECLARE @vRowStart INT
    DECLARE @vTotalRows INT

    SET @vTempTable = '##Tmp' + CAST(DATEPART(YYYY, GETDATE()) AS VARCHAR(4)) +
    CAST(DATEPART(MM, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(DD, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(HH, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(MI, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(SS, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(MS, GETDATE()) AS VARCHAR(3))

    SET @vSQL = 'SELECT ' + @pColumns + ', IDENTITY(INT, 1, 1) AS ROWID INTO ' + @vTempTable + ' FROM ' + @pTableName

    IF @pFilter != '' AND @pFilter IS NOT NULL
    SET @vSQL = @vSQL + ' WHERE ' + @pFilter

    IF @pSort != '' AND @pSort IS NOT NULL
    SET @vSQL = @vSQL + ' ORDER BY ' + @pSort

    EXECUTE (@vSQL)

    -- Get the total number of rows selected
    SET @vTotalRows = @@ROWCOUNT

    -- If page number = 0, set it to the first page
    IF @pPage = 0
    SET @pPage = 1

    -- If page number is beyond the last page, set page to the last page
    IF (@pPage * @pPageRows) > @vTotalRows
    BEGIN
    SET @pPage = @vTotalRows / @pPageRows
    IF (@vTotalRows % @pPageRows) != 0
    SET @pPage = @pPage + 1
    END

    SET @vRowStart = ((@pPage - 1) * @pPageRows) + 1
    SET @vSQL = 'SELECT * FROM ' + @vTempTable + ' WHERE ROWID BETWEEN ' + CAST(@vRowStart AS VARCHAR(10)) +
    ' AND ' + CAST((@vRowStart + @pPageRows - 1) AS VARCHAR(10)) + ' ORDER BY ROWID'
    EXECUTE (@vSQL)

    SET @vSQL = 'DROP TABLE ' + @vTempTable
    EXECUTE (@vSQL)

GO

Hier ein paar Beispiele, wie man es verwenden, um die Northwing Datenbank mit:

EXECUTE [dbo].[GetPage] 'Customers', '*', '', '', 1, 10
EXECUTE [dbo].[GetPage] 'Customers', '*', '', 'CustomerID DESC', 1, 10

Um zu bestätigen, das ist meine Arbeit nicht, sondern ist mit freundlicher Genehmigung von http://www.eggheadcafe.com/PrintSearchContent.asp?LINKID=1055

Cheers, John

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top