在具有不同数据类型的 ORDER BY 子句中使用 CASE 语句
Using a CASE statement in ORDER BY clause with different data types
我想在 ORDER BY
子句中使用 CASE
语句,如下所示:
DECLARE @SortOr TINYINT
SELECT @SortOr = 1
SELECT *
FROM [Table]
ORDER BY CASE WHEN @SortOr = 1 THEN col1
ELSE col2
END
但是它抛出一个错误:
Cannot convert varchar into tinyint.
这背后的逻辑是什么?怎么解决?
将 CASE
语句的所有返回值转换为 VARCHAR
即可。
SQL 服务器尝试隐式转换所有返回值,因为它们是 相同表达式 和 SQL 服务器希望它们真正成为的一部分同一类型;它尝试转换为 INT
,因为 INT
的 precedence 高于 VARCHAR
;所以你应该为此明确设置相同的类型。
@Damien_The_Unbeliever 在评论中完美陈述的根本问题是:
A single CASE
expression has to produce values of one data type. So if you have THEN
s that produce values of different data types, the system uses the precedence rules to decide which ones to convert.
您可以复制您的 CASE
语句来解决这个问题,其中每个 CASE
returns 一个 value/data 类型。这比在另一个答案中建议的将所有值转换为 VARCHAR
更好,后者也应该表现更好(您将必须测试):
所以新的 ORDER BY
子句将如下所示:
ORDER BY CASE WHEN @SortOr = 1 THEN col1
END ,
CASE WHEN @SortOr != 1 THEN col2
END -- If you need DESC it goes after END
我想在 ORDER BY
子句中使用 CASE
语句,如下所示:
DECLARE @SortOr TINYINT
SELECT @SortOr = 1
SELECT *
FROM [Table]
ORDER BY CASE WHEN @SortOr = 1 THEN col1
ELSE col2
END
但是它抛出一个错误:
Cannot convert varchar into tinyint.
这背后的逻辑是什么?怎么解决?
将 CASE
语句的所有返回值转换为 VARCHAR
即可。
SQL 服务器尝试隐式转换所有返回值,因为它们是 相同表达式 和 SQL 服务器希望它们真正成为的一部分同一类型;它尝试转换为 INT
,因为 INT
的 precedence 高于 VARCHAR
;所以你应该为此明确设置相同的类型。
@Damien_The_Unbeliever 在评论中完美陈述的根本问题是:
A single
CASE
expression has to produce values of one data type. So if you haveTHEN
s that produce values of different data types, the system uses the precedence rules to decide which ones to convert.
您可以复制您的 CASE
语句来解决这个问题,其中每个 CASE
returns 一个 value/data 类型。这比在另一个答案中建议的将所有值转换为 VARCHAR
更好,后者也应该表现更好(您将必须测试):
所以新的 ORDER BY
子句将如下所示:
ORDER BY CASE WHEN @SortOr = 1 THEN col1
END ,
CASE WHEN @SortOr != 1 THEN col2
END -- If you need DESC it goes after END