2010-07-09 3 views
7

Ich habe folgende Db und Abfrage. Die Abfrage benötigt zwei Parameter: die Sortierspalte und die Richtung. Allerdings muss ich benutzerdefinierte auf die Abfrage Sortierung hinzufügen (basierend auf dem Fuji sollte zweite erste und Gala kommen, etc.). Dieser Teil funktioniert auch, aber er erzeugt doppelten Code in meiner Abfrage. Dieser Grund, ich bin ziemlich sicher, dass die Leute lassen Sie mich nicht, in Also meine Frage ist:. Ist es eine Möglichkeit, nicht die CASE-Anweisung zu duplizieren?Benutzerdefinierte Sortierung - Wie nicht die Case-Anweisung duplizieren

CREATE TABLE Fruits (
    [type] nvarchar(250), 
    [variety] nvarchar(250), 
    [price] money 
) 
GO 

INSERT INTO Fruits VALUES ('Apple', 'Gala', 2.79) 
INSERT INTO Fruits VALUES ('Apple', 'Fuji', 0.24) 
INSERT INTO Fruits VALUES ('Apple', 'Limbertwig', 2.87) 
INSERT INTO Fruits VALUES ('Orange', 'Valencia', 3.59) 
INSERT INTO Fruits VALUES ('Pear', 'Bradford', 6.05) 

DECLARE @sortColumnName nvarchar(MAX) = 'Variety' 
DECLARE @sortDirection nvarchar(MAX) = 'ASC' 

SELECT ROW_NUMBER() OVER (ORDER BY     
    CASE WHEN @sortColumnName = 'Variety' AND @sortDirection = 'ASC' 
     THEN 
      CASE f.Variety 
       WHEN 'Fuji' THEN 1 
       WHEN 'Gala' THEN 2 
       ELSE 3 
      END  
     END ASC, 
    CASE WHEN @sortColumnName = 'Variety' AND @sortDirection = 'DESC' 
     THEN 
      CASE f.Variety 
       WHEN 'Fuji' THEN 1 
       WHEN 'Gala' THEN 2 
       ELSE 3 
      END  
     END DESC), * 
FROM Fruits f 

Vielen Dank!

Antwort

5

Sie könnten den Sortierschlüssel multiplizieren mit entweder 1 oder -1, je nachdem ob ASC oder DESC angefordert wird:

SELECT ROW_NUMBER() OVER (ORDER BY     
    CASE WHEN @sortColumnName = 'Variety' 
     THEN 
      (CASE f.Variety 
       WHEN 'Fuji' THEN 1 
       WHEN 'Gala' THEN 2 
       ELSE 3 
      END)  
    END 
    * (CASE WHEN @sortDirection = 'ASC' THEN 1 ELSE -1 END)), * 
FROM Fruits f 
1

Warum nicht eine andere Tabelle für vergleichbare Wert haben, kommen auf die Vielfalt Spalte und sortieren auf dem Vergleichswert.

z.

INSERT INTO FruitSort VALUES ('Gala', 2) 
INSERT INTO FruitSort VALUES ('Fuji', 1) 

SELECT ROW_NUMBER() OVER (ORDER BY FruitSort.sortvalue) 
FROM Fruits f 
JOIN FruitSort 
    ON FruitSort.variety == Fruits.variety 

Wäre das nicht der Trick auch während ein bisschen mehr Datenbank-y?

ich nicht sehr geübt habe, so die Syntax ist wahrscheinlich ziemlich kaputt. Ich bin jedoch ziemlich unzufrieden mit dem Konzept von "CASE" -Anweisungen in SQL.

3

Da Sie auf SQL 2008, könnten Sie einen CTE verwenden:

;WITH CTE AS 
(
    SELECT 
     CASE WHEN @sortColumnName = 'Variety' THEN 
      CASE f.Variety 
       WHEN 'Fuji' THEN 1 
       WHEN 'Gala' THEN 2 
       ELSE 3 
      END  
     END AS sort_column, 
     * 
    FROM 
     Fruits F 
) 
SELECT 
    ROW_NUMBER() OVER (
     ORDER BY 
      CASE WHEN @sortDirection = 'DESC' THEN sort_column ELSE 0 END DESC, 
      CASE WHEN @sortDirection = 'ASC' THEN sort_column ELSE 0 END ASC), 
    type, 
    variety, 
    price 
FROM 
    CTE 

Es ist nicht so glatt wie die * -1 Lösung für dieses spezielle Problem, aber es kann auch für andere Situationen angepasst werden, in denen Sie möchte Code Duplikation vermeiden.