【问题标题】:Custom Sort Order - How to not duplicate the Case statement自定义排序顺序 - 如何不重复 Case 语句
【发布时间】:2010-07-09 23:26:41
【问题描述】:

我有以下数据库和查询。该查询采用两个参数:排序列和方向。但是,我必须在查询中添加自定义排序(基于 Fuji 应该排在第一位,Gala 排在第二位,等等)。这部分也有效,但它在我的查询中创建了重复的代码。因此,我很确定人们不会让我签入。所以我的问题是:有没有办法不重复 CASE 语句?

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

【问题讨论】:

    标签: sql tsql sql-server-2008 sql-order-by


    【解决方案1】:

    您可以将排序键乘以 +1 或 -1,具体取决于请求的是 ASC 还是 DESC:

    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
    

    【讨论】:

      【解决方案2】:

      由于您使用的是 SQL 2008,因此您可以使用 CTE:

      ;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
      

      对于这个特定问题,它不像 *-1 解决方案那样巧妙,但它可以适用于您希望避免代码重复的其他情况。

      【讨论】:

        【解决方案3】:

        为什么不用另一个表来比较值,在品种列上连接,并根据比较值排序。

        例如

        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
        

        在更多的数据库化的同时,这不是也能达到目的吗?

        我不是很熟练,所以语法可能很糟糕。不过,我对 SQL 中的“CASE”语句的概念非常不满意。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-03-08
          • 2019-08-20
          • 1970-01-01
          • 2021-09-18
          • 2018-10-22
          相关资源
          最近更新 更多