2010-07-09 20 views
7

Aşağıdaki Db ve sorgularım var. Sorgu iki parametre alır: sıralama sütunu ve yön. Ancak, sorguya özel sıralama eklemem gerekiyor (Fuji'ye göre ilk ve Gala ikinci, vb.). Bu kısım da çalışır, ancak sorgumda çoğaltılmış kod oluşturur. Bundan dolayı, insanların bunu kontrol etmeme izin vermeyeceğine eminim. Bu yüzden sorum şu: CASE bildirimini çoğaltmanın bir yolu var mı?Özel Sıralama Sırası - Vaka ifadesini nasıl kopyalayamazım

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 

Teşekkürler!

cevap

5

Ya +1 göre sıralama anahtarı çarpın veya -1 ASC veya DESC talep olmasına göre olabilir:

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

Neden karşılaştırılabilir değer için başka bir tablo yok, varyete sütun üzerinde katılmak ve sıralama karşılaştırma değerinde.

E.g.

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 

Bu daha fazla veritabanı-yerken de hile yapmaz mı?

Çok pratik değilim, bu yüzden sözdizimi muhtemelen oldukça bozuk. Yine de SQL'de 'CASE' ifadeleri kavramından oldukça memnunum.

3

Eğer SQL 2008 olduğuna göre, bir CTE kullanabilirsiniz:

;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 

Bu sorun için * -1 çözümü gibi kaygan, ama diğer durumlar için adapte edilebilir nerede kod çoğaltmasını önlemek istiyorum.

İlgili konular