【问题标题】: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。

【问题讨论】:

    标签: sql-server


    【解决方案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)
      );
      

      【讨论】:

        猜你喜欢
        • 2014-07-26
        • 2019-02-09
        • 1970-01-01
        • 2014-05-29
        • 1970-01-01
        • 2017-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多