如何在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时转换失败。”
答案 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
,则按Val
和Seq
进行排序。请勿按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
)