2017-04-06 11 views
3

私は残念ながら私はSQLの専門家ではない、私は何をしようとしている2つのパラメータ@OrderBy@SortOrderの結果を並べ替えるですが、結果がソートされますサブクエリの結果にのみ適用されます。たとえば :オーダーとサブクエリー

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? SQLサーバー? 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大規模なテーブルに対するページングのパフォーマンスへの影響を考慮する必要があることに同意しますが、大きなテーブルのtempdbへのROW_NUMBERの書き込みも、 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

関連する問題