Question

J'écrit un SP qui accepte comme colonne pour trier les paramètres et la direction.

Je ne veux pas utiliser SQL dynamique.

Le problème est lié à la définition du paramètre de direction.

Voici le code partiel:

SET @OrderByColumn = 'AddedDate'
SET @OrderDirection = 1;

…

ORDER BY 
    CASE WHEN @OrderByColumn = 'AddedDate' THEN CONVERT(varchar(50), AddedDate)
        WHEN @OrderByColumn = 'Visible' THEN CONVERT(varchar(2), Visible)
        WHEN @OrderByColumn = 'AddedBy' THEN AddedBy
        WHEN @OrderByColumn = 'Title' THEN Title    
    END
Était-ce utile?

La solution

Vous pourriez avoir deux éléments de ORDER BY quasi identiques, l'un ASC et un DESC, et prolonger votre déclaration de CASE pour faire un ou l'autre d'entre eux égale toujours une valeur unique:

ORDER BY
      CASE WHEN @OrderDirection = 0 THEN 1
      ELSE
           CASE WHEN @OrderByColumn = 'AddedDate' THEN CONVERT(varchar(50), AddedDate)
                WHEN @OrderByColumn = 'Visible' THEN CONVERT(varchar(2), Visible)
                WHEN @OrderByColumn = 'AddedBy' THEN AddedBy
                WHEN @OrderByColumn = 'Title' THEN Title
           END
      END ASC,
      CASE WHEN @OrderDirection = 1 THEN 1
      ELSE
           CASE WHEN @OrderByColumn = 'AddedDate' THEN CONVERT(varchar(50), AddedDate)
                WHEN @OrderByColumn = 'Visible' THEN CONVERT(varchar(2), Visible)
                WHEN @OrderByColumn = 'AddedBy' THEN AddedBy           
                WHEN @OrderByColumn = 'Title' THEN Title
           END
      END DESC

Autres conseils

Vous pouvez simplifier le CASE en utilisant ROW_NUMBER qui trie vos données et convertit efficacement dans un format entier à portée de main. D'autant plus que la question est étiquetée SQL Server 2005

Cela élargit aussi assez facilement pour faire face aux sortes secondaires et tertiaires

Je l'ai utilisé multiplicateur pour simplifier encore une fois l'instruction select réelle et de réduire les risques d'évaluation des RBAR dans la ORDER BY

DECLARE @multiplier int;

SELECT @multiplier = CASE @Direction WHEN 1 THEN -1 ELSE 1 END;

SELECT
     Columns you actually want
FROM
    (
    SELECT
         Columns you actually want,
         ROW_NUMBER() OVER (ORDER BY AddedDate) AS AddedDateSort,
         ROW_NUMBER() OVER (ORDER BY Visible) AS VisibleSort,
         ROW_NUMBER() OVER (ORDER BY AddedBy) AS AddedBySort,
         ROW_NUMBER() OVER (ORDER BY Title) AS TitleSort
    FROM
         myTable
    WHERE
         MyFilters...
    ) foo
ORDER BY
     CASE @OrderByColumn
        WHEN 'AddedDate' THEN AddedDateSort
        WHEN 'Visible' THEN VisibleSort    
        WHEN 'AddedBy' THEN AddedBySort
        WHEN 'Title' THEN TitleSort
     END * @multiplier;

Voici un exemple:

CREATE PROCEDURE GetProducts 
( 
    @OrderBy      VARCHAR(50), 
    @Input2       VARCHAR(30) 
) 
AS 
BEGIN 
    SET NOCOUNT ON 

    SELECT Id, ProductName, Description, Price, Quantity 
    FROM Products 
    WHERE ProductName LIKE @Input2 
    ORDER BY 
        CASE             
            WHEN @OrderBy = 'ProductNameAsc' THEN ProductName 
        END ASC, 
        CASE 
            WHEN @OrderBy = 'ProductNameDesc' THEN ProductName 
        END DESC 

END

D'ici:

http://www.dominicpettifer.co.uk/Blog/21/dynamic-conditional-order-by-clause-in-sql-server-t-sql

  

actions ascendant et descendant besoin   être regroupées en boîtier séparé   états, séparés par une virgule. Dans   votre marque de code côté serveur / script sûr   à ajouter « Asc » ou « Desc » sur la   commande par chaîne, ou vous pourriez avoir deux   les paramètres d'entrée de procédure stockée pour   nom de colonne et commande en direction si   vous voulez.

Cela fonctionne bien pour moi - (where, order by, direction, Pagination)

parameters

@orderColumn  int ,
@orderDir  varchar(20),
@start  int ,
@limit  int


select * from items
WHERE        (items.status = 1) 
order by 

CASE WHEN @orderColumn = 0 AND @orderdir = 'desc' THEN items.[category] END DESC,    
CASE WHEN @orderColumn = 0 AND @orderdir = 'asc' THEN items.[category] END ASC,    
CASE WHEN @orderColumn = 1 AND @orderdir = 'desc' THEN items.[category] END DESC,
CASE WHEN @orderColumn = 1 AND @orderdir = 'asc' THEN items.[category] END ASC,
CASE WHEN @orderColumn = 2 AND @orderdir = 'desc' THEN items.[category] END DESC,
CASE WHEN @orderColumn = 2 AND @orderdir = 'asc' THEN items.[category] END ASC

OFFSET @start ROWS FETCH NEXT @limit ROWS ONLY

version plus compacte de répondre , mais comme réponse acceptée, cela fonctionne bien que lorsque les expressions de résultat après THEN ont la même le type.

ORDER BY
    CASE @OrderDirection WHEN 0 THEN
        CASE @sortColumn
           WHEN 'AddedDate' THEN CONVERT(varchar(50), AddedDate)
           WHEN 'Visible' THEN CONVERT(varchar(2), Visible)
           WHEN 'AddedBy' THEN AddedBy
           WHEN 'Title' THEN Title
        END
    END ASC,
    CASE @OrderDirection WHEN 1 THEN
        CASE @sortColumn
           WHEN 'AddedDate' THEN CONVERT(varchar(50), AddedDate)
           WHEN 'Visible' THEN CONVERT(varchar(2), Visible)
           WHEN 'AddedBy' THEN AddedBy
           WHEN 'Title' THEN Title
        END
    END DESC
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top