sql orderby ошибка преобразования при использовании case - PullRequest
1 голос
/ 02 сентября 2011

У меня следующий запрос. При запуске я получаю

Ошибка преобразования типа данных nvarchar в числовой.

Это происходит только тогда, когда @sortorder = 1 или -1, отсортировано по имени. Однако, если оператор case удаляется и используется только order by Name asc, запрос выполняется без ошибок.

Может ли кто-нибудь объяснить, что здесь происходит? спасибо.

DECLARE @SortOrder INT = 1

CREATE TABLE #Results
(
ID INT IDENTITY(1,1),

NameID INT,

Expected NUMERIC(5,1),

Actual NUMERIC(5,1)

)

SELECT Name, Expected, Actual, ID 

FROM (

      SELECT ISNULL(NULLIF(Words.Word, ''), Name.Primary) AS [Name], #Results.Expected, #Results.Actual, #Results.NameID 
    FROM #Results
    INNER JOIN Name ON Name.ID  = #results.NameID 
    LEFT OUTER JOIN Words ON Name.WordID = Words.WordID 
        AND Words.LanguageID = 0
    UNION
    SELECT 'AVG' AS Name,
            CAST(((SUM(#Results.Expected))/COUNT(#Results.ID)) AS NUMERIC(5,1)) AS [Expected],
            CAST(((SUM(Actual))/COUNT(ID)) AS NUMERIC(5,1))AS [Actual],
            -9999 as [ID]
    FROM #Results 
) AS Results

ORDER BY 
    CASE @SortOrder

        WHEN 1 THEN Name    
        WHEN 2 THEN Expected
        WHEN 3 THEN Actual      
        END ASC,    
    CASE @SortOrder 
        WHEN -1 THEN Name   
        WHEN -2 THEN Expected
        WHEN -3 THEN Actual
        END DESC

Ответы [ 3 ]

3 голосов
/ 02 сентября 2011

Для каждого потенциального типа данных требуется отдельное выражение регистра.

ORDER BY 
    CASE @SortOrder
        WHEN 1 THEN Name END,
    CASE @SortOrder
        WHEN 2 THEN Expected
        WHEN 3 THEN Actual      
        END,    
    CASE @SortOrder 
        WHEN -1 THEN Name END DESC,
    CASE @SortOrder   
        WHEN -2 THEN Expected
        WHEN -3 THEN Actual
        END DESC;
3 голосов
/ 02 сентября 2011

Как правило, никогда не используйте что-то подобное. Используйте три отдельных запроса:

if @SortOrder = 1 then
select ... order by Name;
else if @SortOrder = 2 then
select ... order by Expected
else if @SortOrder = 3 then
select ... order by Actual;

То, что вы делаете сейчас, - это на 100% надежный способ запретить оптимизатору запросов SQL Server любой достойный шанс разработать эффективный план: сгенерированный план должен работать для любого значения Переменная @SortOrder, поэтому она должна выполнить сортировку, даже если индекс удовлетворяет порядку по ограничению. Более подробное обсуждение этой темы приведено в Условия динамического поиска в T-SQL .

.

Теперь в вашем случае данные, поступающие из таблицы #temp, еще более важны для разделения случаев выше по стеку. Поскольку таблицы #temp поддерживают индексы, добавьте соответствующий кластерный индекс к самой таблице #temp при ее создании. Что подразумевает использование определенных, отдельных таблиц #temp для Name, Expected или Actual порядка по требованию.

1 голос
/ 02 сентября 2011

Выражение CASE в целом будет приведено к типу данных ветви с наивысшим приоритетом .

Вы можете попробовать привести к sql_variant, поскольку он имеет более высокий приоритет, чем все, кроме UDT, и должен сортироваться правильно.

...