2016-03-14 4 views
1

У меня есть переменная, которая содержит информацию о сортировке, как показано ниже. Информация сортировки может варьироваться в зависимости от столбцов, поэтому я сохранил ее в переменной.Как использовать переменную с предложением Order by в SQL Server

Declare @Sorting varchar(100) = 'AssetCode asc' 

Я использую эту переменную для сортировки с помощью следующего запроса, но это не сортирует данные в соответствии с данными сортировки.

with _result as   
(  
    select   
     ROW_NUMBER() over (order by @Sorting) as RowIndex,   
     *   
    from 
     @Assets   
    where 
     (@Keyword is null or (AssetCode like @Keyword   
           or DisplayName like @Keyword   
           or CategoryName like @Keyword   
           or SiteName like @Keyword   
           or BldgName like @Keyword   
           or SuiteName like @Keyword   
           or Location like @Keyword 
           or SerialVIN like @Keyword  
           or Barcode like @Keyword))  
     ) 

Может кто-нибудь скажет мне, как я могу использовать эту переменную с запросом для сортировки результата? Я буду очень благодарен.

+2

Сделать это как динамически sql ... make @sql nvarchar (max) ... поместить весь запрос в него с порядком по переменной ... и пойти с execute (@sql), и вы получите то, что хотите – Veljko89

+1

Создайте свой запрос как функцию просмотра таблицы, а затем использовать динамический sql с командой execute. –

+0

@ Veljko89 Нет ли короткого пути для этого? –

ответ

1

Вы можете сделать это без динамического SQL, используя простой оператор CASE. Возможно, вы захотите настроить переменную для использования отдельной переменной «ASC»/«DESC», хотя вы можете разобрать свою существующую переменную.

SELECT 
    ROW_NUMBER() OVER (ORDER BY 
          CASE WHEN @order = 'DESC' THEN 
           CASE @Sorting 
            WHEN 'customer_id' THEN RIGHT(REPLICATE('0', 20) + CAST(customer_id AS VARCHAR(20)), 20) 
            WHEN 'first_name' THEN first_name 
            ... etc. 
            ELSE NULL 
           END 
           ELSE NULL 
          END DESC, 
          CASE WHEN @order = 'DESC' THEN 
           CASE @Sorting 
            WHEN 'customer_id' THEN RIGHT(REPLICATE('0', 20) + CAST(customer_id AS VARCHAR(20)), 20) 
            WHEN 'first_name' THEN first_name 
            ... etc. 
            ELSE NULL 
           END 
           ELSE NULL 
          END ASC 
) as RowIndex, 
    * 
FROM 
    @Assets 
WHERE 

Обратите внимание, как customer_id должен быть массируют в строку, которая сортирует правильно как строка. Вам нужно будет сделать то же самое для дат и т. Д., Поскольку все типы данных должны совпадать. Строка - это то, к чему можно привязать все типы данных (хотя технически я должен был бы использовать NVARCHAR).

3

Альтернативный способ, который не использует динамический SQL:

-- order by flags, 1 = ASC, 0 = DESC, NULL = not order by this. 
Declare @SortingByAssetCode bit = NULL; 
Declare @SortingByDisplayName bit = 1; 
Declare @SortingByCategoryName bit = NULL; 
.... 

SELECT ... 
... 
ORDER BY 
    CASE WHEN SortingByAssetCode = 1 THEN AssetCode ELSE 0 END ASC, 
    CASE WHEN SortingByAssetCode = 0 THEN AssetCode ELSE 0 END DESC, 
    CASE WHEN SortingByDisplayName = 1 THEN DisplayName ELSE 0 END ASC, 
    CASE WHEN SortingByDisplayName = 0 THEN DisplayName ELSE 0 END DESC, 
    ... 

Вы не можете динамически изменять порядок следования полей (например, для того, по имени первого дисплея, код актива впоследствии).

Скорее всего, это действительно очень медленно и действительно очень сложно поддерживать.

+0

Этот процесс, который вы определили, оказывает какое-то влияние на производительность? –

+0

Я думаю, да: я сомневаюсь, что СУБД может использовать любые индексы, когда поля находятся в конструкциях 'CASE WHEN'. Это зависит от того, насколько важны индексы в порядке по полям в конкретном случае. И, конечно же, он должен оценивать оператор 'CASE' для каждой возвращаемой строки и всегда заказывается многими выражениями, хотя большинство из них возвращает 0. –

1

Если вы хотите передать такую ​​переменную, вам нужно будет использовать несколько операторов case. Учитывая структуру вашей переменной:

row_number() over ((case when @sorting = 'AssetCode asc' then AssetCode end) asc, 
        (case when @sorting = 'AssetCode desc' then AssetCode end) desc, 
        . . . 
       ) 

Вы должны иметь возможность добавить достаточное количество этих выражений для своих целей. Ключом является отсутствие предложения else. По умолчанию это NULL, поэтому все несоответствия имеют одинаковое значение. Я не вижу причин для разделения asc/desc на отдельную переменную.

И еще одна альтернатива - это динамический SQL. Преимущество Dynamic SQL заключается в том, что оптимизатор может затем использовать индекс для вычисления row_number().

Смежные вопросы