2011-04-26 16 views
29

Me gustaría devolver el número total de registros en la base de datos para poder configurar la paginación. ¿Cómo devuelvo el número total de registros en el DB cuando uso el siguiente método de paginación en SQL Server 2008?Devolver registros totales de SQL Server al usar ROW_NUMBER

ALTER PROCEDURE [dbo].[Nop_LoadAllOptimized] 
    (
     @PageSize int = 20, 
     @PageNumber int = 1, 
     @WarehouseCombinationID int = 1, 
     @CategoryId int = 58, 
     @OrderBy int = 0, 
     @TotalRecords int = null OUTPUT 
    ) 
    AS 
    BEGIN 
    WITH Paging AS (
     SELECT rn = (ROW_NUMBER() OVER (
     ORDER BY 
      CASE WHEN @OrderBy = 0 AND @CategoryID IS NOT NULL AND @CategoryID > 0 
      THEN pcm.DisplayOrder END ASC, 
      CASE WHEN @OrderBy = 0 
      THEN p.[Name] END ASC, 
      CASE WHEN @OrderBy = 5 
      THEN p.[Name] END ASC, 
      CASE WHEN @OrderBy = 10 
      THEN wpv.Price END ASC, 
      CASE WHEN @OrderBy = 15 
      THEN wpv.Price END DESC, 
      CASE WHEN @OrderBy = 20 
      THEN wpv.Price END DESC, 
      CASE WHEN @OrderBy = 25 
      THEN wpv.UnitPrice END ASC 
     )), p.*, pcm.DisplayOrder, wpv.Price, wpv.UnitPrice FROM Nop_Product p 
     INNER JOIN Nop_Product_Category_Mapping pcm ON p.ProductID=pcm.ProductID 
     INNER JOIN Nop_ProductVariant pv ON p.ProductID = pv.ProductID 
     INNER JOIN Nop_ProductVariant_Warehouse_Mapping wpv ON pv.ProductVariantID = wpv.ProductVariantID 
     WHERE pcm.CategoryID = @CategoryId AND (wpv.Published = 1 AND pv.Published = 1 AND p.Published = 1 AND p.Deleted = 0) 
     AND wpv.WarehouseID IN (select WarehouseID from Nop_WarehouseCombination where UserWarehouseCombinationID = @WarehouseCombinationID)  
    ) 
    SELECT TOP (@PageSize) * FROM Paging PG 
    WHERE PG.rn > (@PageNumber * @PageSize) - @PageSize 

    SET @TotalRecords = @@ROWCOUNT 

    END 
+1

Ver [Manera eficiente de obtener @@ rowcount de una consulta utilizando row_number] (http://stackoverflow.com/questions/1038506/efficient-way-of-getting-rowcount-from-a-query-using-row -number/4383164 # 4383164) –

+0

@Martin eso es lo que estaba viendo, pero no dice cómo devolver el número total de filas? – izip

+0

Edité mi comentario y cambié el enlace. ¿A qué enlace se refiere? ¿El SQLServerCentral uno o el StackOverflow uno? Por cierto, es [la parte 2 del artículo de SQL Server Central] (http://www.sqlservercentral.com/articles/paging/70120/) que cubre esto. –

Respuesta

58

normalmente lo hago de esta manera - en realidad nunca comprueba si es muy eficiente desde el punto de vista del rendimiento:

WITH YourCTE AS 
(
    SELECT 
     (list of columns), 
     ROW_NUMBER() OVER (ORDER BY ......) AS 'RowNum' 
    FROM dbo.YourBaseTable 
) 
SELECT 
    *, 
    (SELECT MAX(RowNum) FROM YourCTE) AS 'TotalRows' 
FROM 
    YourCTE 
WHERE 
    RowNum BETWEEN 101 AND 150 

Básicamente, el valor RowNum tendrán valores de 1 a través del total de filas (si no tiene un PARTITION BY en su CTE) y seleccionando , obtendrá el número total de filas.

+1

Gracias. ¿Cómo se asignan las TotalRows a un parámetro de salida desde un proceso de tienda? Funciona en ambos sentidos, el suyo y Martins, pero me gustaría devolverlo como un param en lugar de una nueva columna en mi conjunto de datos. EDITAR, lo obtuve: @TotalRecords = PG.TotalRows – izip

+1

awesome ....... :) – Umer

+1

¡Muy listo! Funciona muy bien (y rápido) para mí. –

24

Bueno, yo había usado #temp tablas en pasado, pero encontré otra solución usando Count(..) OVER() para encontrar el número total de filas hace unos días. Funciona así:

SELECT COUNT(id) OVER() [Total], ROW_NUMBER() OVER(ORDER BY id DESC) [RowNo] 
, [other columns] 
FROM Table 

La página de referencia es here.

+0

Esta es la mejor solución que he encontrado para este problema hasta el momento. Tiene el beneficio de no afectar significativamente el tiempo de ejecución de la consulta. – bcleary

+1

El problema aquí es que RowNo no se puede usar dentro de la cláusula WHERE. – Fedor

+0

Gracias hombre. Me salvaste el tiempo ... –

Cuestiones relacionadas