多列Order by子句的语法不正确

时间:2019-01-09 10:47:45

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

如何在case语句中编写具有多列的order by子句?

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Val,Seq
 ELSE Seq END

也尝试过

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Convert(int,Val) 
 WHEN @T='ABC' Then Convert(nvarchar,Seq)
 ELSE Seq END

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Val,Seq
 ELSE Seq END

下面给出的代码也会引发错误:

  

“该语句给出了错误:执行存储过程时,将nvarchar值'EX-02-60'转换为数据类型int时转换失败。”

3 个答案:

答案 0 :(得分:7)

让我们创建一个包含您的列的表

CREATE TABLE T(
  Val VARCHAR(45),
  Seq INT,
  Sequence INT
);

INSERT INTO T VALUES
('A', 1, 2),
('C', 2, 1),
('B', 3, 3);

现在,让我们看一下您的代码,然后带来条件:

这是您的代码:

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Val,Seq
 ELSE Sequence END
  • 如果@T = 'ABC,则按ValSeq进行排序。请勿Sequence进行排序。
  • 如果@T <> 'ABC',则用Sequence订购

如果您运行此查询:

--You was trying--

DECLARE @T VARCHAR(3) = 'ABC'; --wil works only when @T <> ABC

SELECT *
FROM T
ORDER BY CASE WHEN @T='ABC' THEN Seq END, --Take INT
         CASE WHEN @T='ABC' THEN Val --Take Varchar
              ELSE Sequence -- Take INT
         END;

如果@T = 'ABC'

,它将引发以下错误
  

消息245级别16状态1的第5行

     

将varchar值'A'转换为数据类型int时转换失败。

与您一样

  

将nvarchar值'EX-02-60'转换为数据类型int时转换失败。

现在,根据您提供的条件,这是您想要的:

--Fixes--

DECLARE @T VARCHAR(3) = '1'; --Try to change it to ABC too

SELECT *
FROM T
ORDER BY CASE WHEN @T='ABC' THEN Val END, --Take varchar
         CASE WHEN @T='ABC' THEN Seq -- Take INT
              ELSE Sequence -- Take INT
         END;
/*
 IF @T = ABC
 ORDER BY Val, Seq; NOT Sequence

 IF @T <> ABC
 ORDER BY ONLY Sequence
*/

这是 Live demo

答案 1 :(得分:1)

我怀疑您追求的是:

ORDER BY CASE @T WHEN 'ABC' THEN Val END,
         CASE @T WHEN 'ABC' THEN Seq END,
         [Sequence];

详细说明您尝试失败的原因。首先:

WHERE  Type = @T  ORDER BY 
 CASE 
 WHEN @T='ABC' Then Val,Seq
 ELSE Sequence END

CASE是一个返回标量值的表达式。您的WHEN在这里尝试返回2个值。那是不允许的。

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Convert(int,Val) 
 WHEN @T='ABC' Then Convert(nvarchar,Seq)
 ELSE Seq END

由于CASE返回一个标量值,因此它只能返回一个数据类型。 CASE表达式使用数据类型优先级,而int的优先级高于nvarchar,因此Seq将隐式转换为int;我会冒一个失败的猜测。

答案 2 :(得分:0)

ORDER BY中“值”的数据类型应始终相同。在这里,您将获得转换错误,因为在第一种情况下,数据类型为INT,在第二种情况下,数据类型为Varchar。因此,对于更安全的方式,您可以使用以下方法

;WITH CTE
AS
(
    SELECT
        RN_Val = ROW_NUMBER() OVER(ORDER BY Val),
        RN_Seq = ROW_NUMBER() OVER(ORDER BY Seq),
        *
        FROM YourTable
)
SELECT
    *
    FROM CTE
        ORDER BY 
        (
            CASE @T
                WHEN 'ABC' THEN RN_Val
                WHEN 'XYZ' THEN RN_Seq
            END
        )