Efficient Data Pagination Using OFFSET-FETCH in SQL Stored Procedures with Complex Joins

 Efficient Data Pagination Using OFFSET-FETCH in SQL Stored Procedures with Complex Joins


Introduction


When dealing with large datasets in SQL Server, fetching all records at once can lead to performance issues. Instead, we can implement pagination using OFFSET-FETCH, especially when working with complex joins. This method allows fetching a subset of data efficiently, improving both performance and scalability.


This article will guide you through implementing OFFSET-FETCH in a SQL stored procedure with complex joins.



---


Understanding OFFSET-FETCH in SQL Server


The OFFSET and FETCH clauses are used with ORDER BY to skip a specified number of rows and retrieve only a limited set of records.


Syntax


SELECT columns

FROM TableName

ORDER BY ColumnName

OFFSET @Offset ROWS

FETCH NEXT @PageSize ROWS ONLY;


OFFSET @Offset ROWS: Skips the specified number of rows.


FETCH NEXT @PageSize ROWS ONLY: Fetches the next batch of records.




---


Implementing Pagination in a Stored Procedure with Complex Joins


Scenario


Assume we have the following tables:


1. Orders (OrderID, CustomerID, OrderDate, TotalAmount)



2. Customers (CustomerID, CustomerName, Country)



3. OrderDetails (OrderDetailID, OrderID, ProductID, Quantity, UnitPrice)



4. Products (ProductID, ProductName, CategoryID, Price)




We want to retrieve paginated order details, including customer information, product details, and total order amount, while allowing sorting by OrderDate.



---


Creating the Stored Procedure


CREATE PROCEDURE GetPaginatedOrders

    @PageNumber INT,

    @PageSize INT

AS

BEGIN

    SET NOCOUNT ON;


    DECLARE @Offset INT = (@PageNumber - 1) * @PageSize;


    WITH OrderData AS 

    (

        SELECT 

            o.OrderID, 

            c.CustomerName, 

            c.Country, 

            o.OrderDate, 

            p.ProductName, 

            od.Quantity, 

            od.UnitPrice, 

            (od.Quantity * od.UnitPrice) AS TotalPrice,

            ROW_NUMBER() OVER (ORDER BY o.OrderDate DESC) AS RowNum

        FROM Orders o

        INNER JOIN Customers c ON o.CustomerID = c.CustomerID

        INNER JOIN OrderDetails od ON o.OrderID = od.OrderID

        INNER JOIN Products p ON od.ProductID = p.ProductID

    )

    SELECT * 

    FROM OrderData

    ORDER BY OrderDate DESC

    OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY;

END;



---


Breaking Down the Query


1. Using CTE (Common Table Expression):


We first join the Orders, Customers, OrderDetails, and Products tables.


We calculate the TotalPrice (Quantity * UnitPrice).


We use ROW_NUMBER() to generate row numbers for sorting (optional).




2. Pagination Logic:


The @PageNumber and @PageSize parameters control the number of records fetched.


The @Offset value determines the starting point of the result set.


The OFFSET-FETCH clause efficiently retrieves only the required rows.






---


Executing the Stored Procedure


To fetch page 2 with 10 records per page, run:


EXEC GetPaginatedOrders @PageNumber = 2, @PageSize = 10;



---


Advantages of Using OFFSET-FETCH for Pagination


✔ Efficient Memory Usage: Only a subset of data is loaded into memory.

✔ Scalability: Works well with millions of records.

✔ Improved Query Performance: Fetching only the required rows reduces execution time.

✔ Flexibility: Supports sorting and filtering based on business requirements.



---


Alternative Approach: Using ROW_NUMBER()


If SQL Server 2012 or earlier is used, ROW_NUMBER() can be used instead of OFFSET-FETCH.


WITH OrderData AS 

(

    SELECT 

        o.OrderID, c.CustomerName, c.Country, o.OrderDate, 

        p.ProductName, od.Quantity, od.UnitPrice, 

        (od.Quantity * od.UnitPrice) AS TotalPrice,

        ROW_NUMBER() OVER (ORDER BY o.OrderDate DESC) AS RowNum

    FROM Orders o

    INNER JOIN Customers c ON o.CustomerID = c.CustomerID

    INNER JOIN OrderDetails od ON o.OrderID = od.OrderID

    INNER JOIN Products p ON od.ProductID = p.ProductID

)

SELECT * 

FROM OrderData

WHERE RowNum BETWEEN (@PageNumber - 1) * @PageSize + 1 

                  AND @PageNumber * @PageSize;


This achieves the same result but may be slower for large datasets compared to OFFSET-FETCH.



---


Conclusion


Using OFFSET-FETCH in SQL Server stored procedures allows efficient pagination while handling comp

lex joins. It ensures optimal performance and scalability, making it ideal for large datasets.

Comments

Popular posts from this blog

Maxpooling vs minpooling vs average pooling

Understand the Softmax Function in Minutes

Percentiles, Deciles, and Quartiles