开发者

sql orderby conversion error when case is used

开发者 https://www.devze.com 2023-04-02 05:52 出处:网络
I have the following query. When run I receive Error converting data type nvarchar to numeric. This only occurs when @sortorder = 1 or -1, sorted by name. However, if the case statement is remove

I have the following query. When run I receive

Error converting data type nvarchar to numeric.

This only occurs when @sortorder = 1 or -1, sorted by name. However, if the case statement is removed and just order by Name asc is used the query run without error.

Could anyone explain whats going on here? thanks.

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


You need a separate case expression for each potential data type.

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;


As a general rule, don't ever use something like that. Use three separate queries:

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;

What you're doing now is the 100% sure way to deny the SQL Server query optimizer any decent chance to come up with an efficient plan: the generated plan has to work for any value of the @SortOrder variable, therefore it must do a sort even if an index would satisfy the order by constraint. For a more lengthier discussion on the topic read Dynamic Search Conditions in T-SQL.

Now in your case the data coming from a #temp table is even more important to separate the cases higher up the stack. Since #temp tables support indexes, add the appropriate clustered index to the #temp table itself when you create it. Which implies using specific, separate, #temp tables for Name, Expected or Actual order by requirement.


The CASE expression as a whole will be coerced to the data type of the branch with the highest precedence.

You could try casting to sql_variant as this has a higher precedence than everything except UDTs and should sort correctly.

0

精彩评论

暂无评论...
验证码 换一张
取 消