为啥我不能在计算列的 case 语句中使用子查询
Posted
技术标签:
【中文标题】为啥我不能在计算列的 case 语句中使用子查询【英文标题】:Why Can't I use sub-queries within a case statement in a calculated column为什么我不能在计算列的 case 语句中使用子查询 【发布时间】:2017-04-10 22:45:59 【问题描述】:我正在尝试运行以下查询:
create table MyTable (
TableIndex bigint primary key identity(1,1) not null,
ForeignKey1 int not null,
ForeignKey2 char(16) not null,
fldSomeNumber float(24),
fldScore as cast(case
when fldSomeNumber is null or fldCSIPercentage=0 then 0
when fldSomeNumber <= 0.09 then (select fldTenthScore from tblScores where ScorePrimaryKey=MyTable.ForeignKey2)
when fldSomeNumber <= 0.9 then (select fld1Score from tblScores where ScorePrimaryKey=MyTable.ForeignKey2)
...
else 100 end as float(24))
);
但我不断收到以下错误:“在此上下文中不允许子查询。只允许标量表达式。”不能将子选择放在这样的计算列中吗?
我正在运行 SQL Server Express 2016。
【问题讨论】:
【参考方案1】:您根本无法使用单个表完成您的要求,您需要使用视图并将计算列放在视图上。
所以看起来像这样的视图
CREATE VIEW MyView AS
SELECT
cast(case
when fldSomeNumber is null or fldCSIPercentage=0 then 0
when fldSomeNumber <= 0.09 then tblScores.fldTenthScore
when fldSomeNumber <= 0.9 then tblScores.fld1Score
...
else 100 end as float(24)) AS fldScore
FROM
MyTable
INNER JOIN tblScores
ON tblScores.ScorePrimaryKey = MyTable.ForeignKey2
查看此问题的第二个答案:
formula for computed column based on different table's column
【讨论】:
【参考方案2】:使用CREATE TABLE
时,必须分别使用列名和数据类型,但这里写fldScore
列名时,插入的是值而不是数据类型。因为CASE
结构返回一个值,而您只将该值转换为浮点数。
但是,如果您的意思是计算列,则只能使用当前表中的列来定义计算列,而不是来自其他表。
【讨论】:
这是一个没有指定数据类型的计算列。【参考方案3】:用函数解决这个问题的方法(mallan1121推荐的)如下:
IF EXISTS (
SELECT * FROM sysobjects WHERE id = object_id('fnCalculateScore')
AND xtype IN ('FN', 'IF', 'TF')
)
DROP FUNCTION fnCalculateScore
go
create function fnCalculateScore (
@SomeNumber float(24),
@SomeKey char(16)
)
returns float(24)
with schemabinding
as
begin
return (select case
when @SomeNumber is null or @SomeNumber=0 then 0
when @SomeNumber <= 0.09 then (select fldTenthScore from dbo.tblScores where ScorePrimaryKey=@SomeKey)
when @SomeNumber <= 0.9 then (select fld1Score from dbo.tblScores where ScorePrimaryKey=@SomeKey)
...
else 100 end as float(24))
end
go
create table MyTable (
TableIndex bigint primary key identity(1,1) not null,
ForeignKey1 int not null,
ForeignKey2 char(16) not null,
fldSomeNumber float(24),
fldScore as dbo.fnCalculateScore(fldSomeNumber, ForeignKey2)
);
【讨论】:
以上是关于为啥我不能在计算列的 case 语句中使用子查询的主要内容,如果未能解决你的问题,请参考以下文章
不使用 EXISTS 嵌套 case 语句引入子查询时,选择列表中只能指定一个表达式