简体   繁体   中英

order by and sub-query

I am in trouble with a basical stored procedure, unfortunately I am not a sql expert, what I am trying to do is sort offers result by 2 parameters, @OrderBy and @SortOrder , however the result is sorted only on the result of the sub-query. For example:

exec [dbo].[GetTest2] @Page=0,@Limit=150,@OrderBy=N'NetworkName',@SortOrder=N'asc'

it works as expected, but

exec [dbo].[GetTest2] @Page=0,@Limit=15,@OrderBy=N'NetworkName',@SortOrder=N'asc'

doesn't works because the subquery doesn't return all the records.

how can I sort over the entire recordset?

USE [MyContext]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter PROCEDURE [dbo].[GetTest2] 
    @Page int = 0,
    @Limit int = 10,
    @OrderBy nvarchar(50) = 'OfferId',
    @Name nvarchar(100) = NULL,
    @SortOrder nvarchar(50) = 'asc'
AS
BEGIN
    SET NOCOUNT ON;
    SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY @OrderBy) AS ROWNUMBER, 
                  COUNT(*) OVER() AS [Total_Rows], 
                  a.Name AS NetworkName, 
                  o.*  

                  FROM offers AS o 
                    left outer join AffiliateNetworks AS a ON o.NetworkId = a.Id

                  WHERE (@Name IS NULL OR o.Name LIKE '%' + @Name + '%' )) AS Paged 
    WHERE 

    Paged.ROWNUMBER > @Limit * @Page AND 
    Paged.ROWNUMBER <= (@Limit * @Page) + @Limit

    order by 
                    case 
                        when @SortOrder <> 'asc' then NULL
                        when @OrderBy = 'Name' then Name
                        end ASC,
                    case 
                        when @SortOrder <> 'asc' then NULL
                        when @OrderBy = 'NetworkName' then NetworkName
                        end ASC,
                    case 
                        when @SortOrder <> 'desc' then NULL
                        when @OrderBy = 'Name' then Name
                        end DESC,
                    case 
                        when @SortOrder <> 'desc' then NULL
                        when @OrderBy = 'NetworkName' then NetworkName
                        end DESC

END 

You might consider adding the sorting within the ROW_NUMBER to keep the paging consistent. I wrapped the sub-query in a CTE to make it a little easier to read.

ALTER PROCEDURE [dbo].[GetTest2] 
    @Page int = 0,
    @Limit int = 10,
    @OrderBy nvarchar(50) = 'OfferId',
    @Name nvarchar(100) = NULL,
    @SortOrder nvarchar(50) = 'asc'
AS
BEGIN
    SET NOCOUNT ON;

    ;WITH Paged AS (
        SELECT ROW_NUMBER() OVER (
            ORDER BY
                CASE WHEN @SortOrder = 'ASC'
                    THEN (CASE @OrderBy WHEN = 'Name' THEN Name WHEN 'NetworkName' THEN a.Name END) END ASC,
                CASE WHEN @SortOrder = 'DESC'
                    THEN (CASE @OrderBy WHEN = 'Name' THEN Name WHEN 'NetworkName' THEN a.Name END) END DESC)
            ) AS ROWNUMBER,
            COUNT(*) OVER() AS [Total_Rows],
            a.Name AS NetworkName,
            o.*
        FROM offers AS o 
            left outer join AffiliateNetworks AS a ON o.NetworkId = a.Id
        WHERE (@Name IS NULL OR o.Name LIKE '%' + @Name + '%' )
    )
        SELECT *
        FROM Paged
        WHERE ROWNUMBER - (@Limit * @Page) BETWEEN 1 AND @Limit
        ORDER BY ROWNUMBER
END
GO

As mentioned in comments, ROW_NUMBER may not be best construct for paging in later versions of SQL Server. If you are using at least 2012 or higher, then you can use the OFFSET and FETCH NEXT to do your paging. Then your query becomes something like this:

    SELECT
        COUNT(*) OVER() AS [Total_Rows],
        CASE @OrderBy WHEN = 'Name' THEN o.Name WHEN 'NetworkName' THEN a.Name END AS SortName,
        a.Name AS NetworkName,
        o.*
    FROM offers AS o 
        left outer join AffiliateNetworks AS a ON o.NetworkId = a.Id
    WHERE (@Name IS NULL OR o.Name LIKE '%' + @Name + '%' )
    ORDER BY
        CASE WHEN @SortOrder = 'ASC' THEN SortName ELSE NULL END ASC,
        CASE WHEN @SortOrder = 'DESC' THEN SortName ELSE NULL END DESC
    OFFSET (@Page * @Limit) ROWS
    FETCH NEXT @Limit ROWS ONLY;

Try this:

order by 
                    case 
                        when @OrderBy = 'Name' and @SortOrder = 'asc' then Name
                        when @OrderBy = 'NetworkName' and @SortOrder = 'asc' then NetworkName
                        end ASC,

                    case when @OrderBy = 'Name' and @SortOrder = 'desc' then Name
                         when @OrderBy = 'NetworkName' and @SortOrder = 'desc' then NetworkName
                         end DESC

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM