Пользовательский Порядок сортировки - Как не копировать Оператор выбора

У меня есть следующий дб и запрос. Запрос берет два параметра: столбец вида и направление. Однако я должен добавить, пользовательская сортировка к запросу (на основе Фуджи должен прибыть первая и Праздничная секунда, и т.д.). Эта часть также работает, но она создает дублированный код в моем запросе. Из-за этого я - вполне уверенные люди, не позволит мне регистрировать это. Таким образом, мой вопрос: существует ли способ не копировать Оператор выбора?

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
7
задан Kara 1 February 2019 в 19:06
поделиться

3 ответа

Вы можете умножить ключ сортировки на +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
5
ответ дан 7 December 2019 в 03:10
поделиться

Почему бы не иметь еще одну таблицу для сопоставимого значения, объединить по столбцу сорта и сортировать по сопоставимому значению.

Например,

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

Разве это не поможет и в этом случае, хотя и будет немного больше соответствовать базе данных?

Я не очень практичен, поэтому синтаксис, вероятно, довольно сломан. Однако мне очень не нравится концепция операторов 'CASE' в SQL.

1
ответ дан 7 December 2019 в 03:10
поделиться

Поскольку вы используете 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
ответ дан 7 December 2019 в 03:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: