在具有不同数据类型的 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,因为 INTprecedence 高于 VARCHAR;所以你应该为此明确设置相同的类型。

@Damien_The_Unbeliever 在评论中完美陈述的根本问题是:

A single CASE expression has to produce values of one data type. So if you have THENs 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