Pregunta

¿Cómo puedo paginar los resultados en SQL Server 2005?

Lo probé en SQL Server 2000, pero no había una forma confiable de hacerlo.Ahora me pregunto si SQL Server 2005 tiene algún método integrado.

Lo que quiero decir con paginación es, por ejemplo, que si enumero a los usuarios por su nombre de usuario, quiero poder devolver solo los primeros 10 registros, luego los 10 registros siguientes y así sucesivamente.

Cualquier ayuda sería muy apreciada.

¿Fue útil?

Solución

Puedes usar the Row_Number() función.Se utiliza de la siguiente manera:

SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users

De lo cual se obtendrá un conjunto de resultados con un RowID campo que puede utilizar para desplazarse.

SELECT * 
FROM 
    ( SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
      FROM Users 
    ) As RowResults
WHERE RowID Between 5 AND 10

etc.

Otros consejos

Si está intentando obtenerlo en una sola declaración (el total más la paginación).Es posible que necesite explorar el soporte de SQL Server para la cláusula de partición por (funciones de ventana en términos ANSI SQL).En Oracle, la sintaxis es como el ejemplo anterior usando número_fila(), pero también agregué una cláusula de partición por para obtener el número total de filas incluidas con cada fila devuelta en la paginación (el total de filas es 1262):

SELECT rn, total_rows, x.OWNER, x.object_name, x.object_type
FROM (SELECT COUNT (*) OVER (PARTITION BY owner) AS TOTAL_ROWS,
         ROW_NUMBER () OVER (ORDER BY 1) AS rn, uo.*
         FROM all_objects uo
         WHERE owner = 'CSEIS') x
WHERE rn BETWEEN 6 AND 10

Tenga en cuenta que tengo donde propietario = 'CSEIS' y mi partición está en propietario.Entonces los resultados son:

RN  TOTAL_ROWS  OWNER   OBJECT_NAME            OBJECT_TYPE
6   1262    CSEIS   CG$BDS_MODIFICATION_TYPES   TRIGGER
7   1262    CSEIS   CG$AUS_MODIFICATION_TYPES   TRIGGER
8   1262    CSEIS   CG$BDR_MODIFICATION_TYPES   TRIGGER
9   1262    CSEIS   CG$ADS_MODIFICATION_TYPES   TRIGGER
10  1262    CSEIS   CG$BIS_LANGUAGES            TRIGGER

La respuesta aceptada para esto en realidad no funciona para mí... Tuve que pasar por un aro más para que funcionara.

Cuando probé la respuesta

SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
WHERE RowID Between 0 AND 9

falló, quejándose de que no sabía qué era RowID.

Tuve que envolverlo en una selección interna como esta:

SELECT * 
FROM
    (SELECT
    Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
    FROM Users
    ) innerSelect
WHERE RowID Between 0 AND 9

y luego funcionó.

Cuando necesito paginar, normalmente también uso una tabla temporal.Puede utilizar un parámetro de salida para devolver el número total de registros.Las declaraciones de caso en select le permiten ordenar los datos en columnas específicas sin necesidad de recurrir a SQL dinámico.

--Declaration--

--Variables
@StartIndex INT,
@PageSize INT,
@SortColumn VARCHAR(50),
@SortDirection CHAR(3),
@Results INT OUTPUT

--Statements--
SELECT @Results = COUNT(ID) FROM Customers
WHERE FirstName LIKE '%a%'

SET @StartIndex = @StartIndex - 1 --Either do this here or in code, but be consistent
CREATE TABLE #Page(ROW INT IDENTITY(1,1) NOT NULL, id INT, sorting_1 SQL_VARIANT, sorting_2 SQL_VARIANT)
INSERT INTO #Page(ID, sorting_1, sorting_2)
SELECT TOP (@StartIndex + @PageSize)
    ID,
    CASE
        WHEN @SortColumn='FirstName' AND @SortDirection='ASC' THEN CAST(FirstName AS SQL_VARIANT)
        WHEN @SortColumn='LastName' AND @SortDirection='ASC' THEN CAST(LastName AS SQL_VARIANT)
        ELSE NULL
    END AS sort_1,
    CASE
        WHEN @SortColumn='FirstName' AND @SortDirection='DES' THEN CAST(FirstName AS SQL_VARIANT)
        WHEN @SortColumn='LastName' AND @SortDirection='DES' THEN CAST(LastName AS SQL_VARIANT)
        ELSE NULL
    END AS sort_2
FROM (
    SELECT
        CustomerId AS ID,
        FirstName,
        LastName
    FROM Customers
    WHERE
        FirstName LIKE '%a%'
) C
ORDER BY sort_1 ASC, sort_2 DESC, ID ASC;

SELECT
    ID,
    Customers.FirstName,
    Customers.LastName
FROM #Page
INNER JOIN Customers ON
    ID = Customers.CustomerId
WHERE ROW > @StartIndex AND ROW <= (@StartIndex + @PageSize)
ORDER BY ROW ASC

DROP TABLE #Page

Creo que, lamentablemente, necesitaría realizar una consulta por separado para lograrlo.

Pude lograr esto en mi puesto anterior usando la ayuda de esta página:Paginación en DotNet 2.0

También lo tienen contando filas por separado.

Esto es lo que hago para paginar:Todas mis consultas importantes que deben paginarse están codificadas como inserciones en una tabla temporal.La tabla temporal tiene un campo de identidad que actuará de manera similar al número_fila() mencionado anteriormente.Almaceno el número de filas en la tabla temporal en un parámetro de salida para que el código de llamada sepa cuántos registros hay en total.El código de llamada también especifica qué página desea y cuántas filas por página, que se seleccionan de la tabla temporal.

Lo bueno de hacerlo de esta manera es que también tengo un enlace "Exportar" que le permite obtener todas las filas del informe como CSV encima de cada cuadrícula de mi aplicación.Este enlace utiliza el mismo procedimiento almacenado:simplemente devuelve el contenido de la tabla temporal en lugar de realizar la lógica de paginación.Esto apacigua a los usuarios que odian la paginación y quieren ver todo, y quiero ordenarlo de un millón de maneras diferentes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top