2010-10-07 18 views
12

Rédaction d'une procédure stockée dans MS SQL Server 2008 R2, je veux éviter d'utiliser DSQL ...ORDER conditionnelle SQL PAR ASC/DESC pour les colonnes alpha

Je voudrais la méthode de tri (ASC ou DESC) être conditionnel.

Maintenant, avec une colonne numérique, je voudrais simplement utiliser une déclaration de cas et annuler la valeur à imiter ASC ou DESC ... Ce est:

... ORDER BY CASE @OrderAscOrDesc WHEN 0 THEN [NumericColumn] ELSE -[NumericColumn] END ASC 

Quelle est une méthode appropriée pour le faire avec un colonne alpha?

EDIT: J'ai pensé d'une manière intelligente, mais il semble terriblement inefficace ... Je pourrais insérer ma colonne alpha ordonnée dans une table temporaire avec un autonumber, puis trier par le numéro automatique en utilisant la méthode décrite ci-dessus.

EDIT2:

Qu'est-ce que vous les gars pensent de cette approche?

ORDER BY CASE @OrderAscOrDesc WHEN 0 THEN [AlphaColumn] ELSE '' END ASC, 
CASE @OrderAscOrDesc WHEN 0 THEN '' ELSE [AlphaColumn] END DESC 

Je ne sais pas si forcer une sorte sur une colonne uniforme est plus efficace que le nombre de chaînes provenant triées si

Répondre

27

Une option

;WITH cQuery AS 
(
    SELECT 
     *, 
     ROW_NUMBER() OVER (ORDER BY SortColumn) AS RowNum 
    FROM 
     MyTable 
) 
SELECT 
    * 
FROM 
    cQuery 
ORDER BY 
    RowNum * @Direction --1 = ASC or -1 = DESC 

Ou CASE qui à mon humble avis est un peu plus laid

ORDER BY 
    CASE WHEN 'ASC' THEN SortColumn ELSE '' END ASC, 
    CASE WHEN 'DESC' THEN SortColumn ELSE '' END DESC 
+0

intelligent, assez semblable à ma solution que j'ai posté dans l'édition. J'espère que quelque chose de plus efficace que de dériver une autre copie triée des données juste pour produire un ordre de tri numérique .... – Matthew

+0

@Matthew PK: soit vous devez substituer la chaîne pour un nombre correspondant, ou ajouter des tris fictifs pour non Cas pertinents Rien d'autre * vraiment * intelligent j'ai peur – gbn

+0

Que penses-tu de l'approche "deux ORDER BY" dans mon deuxième montage? – Matthew

1

C'est l'un de ces cas où des solutions spécifiques peuvent être préférables prefe rable aux génériques, en particulier lorsque nous traitons de grandes quantités de données. Je voudrais:

IF @OrderAscOrDesc = 0 THEN BEGIN 
    SELECT ... 
    FROM ... 
    ORDER BY [AlphaColumn] ASC 
END ELSE BEGIN 
    SELECT ... 
    FROM ... 
    ORDER BY [AlphaColumn] DESC 
END 

Si vous avez un index sur [AlphaColumn], vous pourriez parfois obtenir un meilleur plan avec une requête plus spécifique, qu'avec un one-size-fits-all générique.

Edit: pour faciliter la réutilisation de code, vous pouvez envelopper votre sélection dans une UDF en ligne - il se produira aussi bien:

IF @OrderAscOrDesc = 0 THEN BEGIN 
    SELECT ... 
    FROM YourInlineUdf(...) 
    ORDER BY [AlphaColumn] ASC 
END ELSE BEGIN 
    SELECT ... 
    FROM YourInlineUdf(...) 
    ORDER BY [AlphaColumn] DESC 
END 
+0

Je suis d'accord avec le principe que vous ' Je l'ai énoncé. Dans mon application particulière, je préférerais ne pas le faire car la requête est relativement longue et utilise un certain nombre de jointures. Mon souci serait de dupliquer le code 6 fois ou plus, rendant la maintenance et les futures mises à jour difficiles. – Matthew

+0

@Matthew PK: pour faciliter la réutilisation du code, vous pouvez envelopper votre select dans un UDF en ligne - il fonctionnera aussi bien –