我有以下查询。我跑的时候收到了
将数据类型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
答案 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表本身。这意味着按要求为Name
,Expected
或Actual
订单使用特定的,单独的#temp表。
答案 2 :(得分:1)
CASE
表达式作为一个整体将被强制转换为highest precedence分支的数据类型。
您可以尝试转换为sql_variant
,因为它具有比UDT之外的所有内容更高的优先级,并且应该正确排序。