使用case时的转换错误的sql顺序

时间:2011-09-02 15:25:36

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

我有以下查询。我跑的时候收到了

  

将数据类型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 个答案:

答案 0 :(得分:3)

每种潜在的数据类型都需要一个单独的case表达式。

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;

答案 1 :(得分:3)

作为一般规则,不要使用类似的东西。使用三个单独的查询:

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变量,因此即使索引满足约束的顺序,必须进行排序。有关该主题的更长时间的讨论,请阅读Dynamic Search Conditions in T-SQL

现在,在您的情况下,来自#temp表的数据对于分离堆栈中较高的情况更为重要。由于#temp表支持索引,因此在创建时将相应的聚簇索引添加到#temp表本身。这意味着按要求为NameExpectedActual订单使用特定的,单独的#temp表。

答案 2 :(得分:1)

CASE表达式作为一个整体将被强制转换为highest precedence分支的数据类型。

您可以尝试转换为sql_variant,因为它具有比UDT之外的所有内容更高的优先级,并且应该正确排序。