2017-04-06 40 views
3

我麻煩了basical存儲過程,可惜我不是一個SQL專家,我所要做的是排序2個參數,@OrderBy@SortOrder提供結果,但結果進行排序只有子查詢的結果。 例如:ORDER BY和子查詢

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

它能正常工作,但

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

不工作,因爲子查詢不返回所有記錄。

我怎麼樣在整個記錄?

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 
+1

SQL不支持此構造。 使用存儲過程中,SQL方言是非常重要的。您使用哪種SQL語言?甲骨文? DB2? SQLServer的? Postgres的?等 –

+0

我使用MS SQLSERVER,這是支持這一說法 – InferOn

回答

2

,可以考慮添加的ROW_NUMBER中的排序保持一致分頁。我在CTE中封裝了子查詢,使其更容易閱讀。

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 

正如評論所說,ROW_NUMBER可能不是最好的構建在SQL Server的更高版本的分頁。如果您正在使用至少2012或更高版本,那麼你可以使用OFFSETFETCH NEXT做分頁。然後您的查詢變成如下所示:

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; 
+0

很好的回答+1但是,如果有大量的行,也許是臨時表會比CTE更好。 – Jodrell

+0

固定的小語法錯誤(左額外的「=」萬一) –

+1

@Jodrell我同意你需要考慮分頁對大表的性能影響,但我也想像ROW_NUMBER寫大表的tempdb中完全也可能造成問題。 OFFSET/FETCH NEXT對於大型數據集來說可能是更好的選擇。 –

0

試試這個:

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 
+0

感謝的很多,但是你的答案是不相關的問題 – InferOn