首页 > 解决方案 > 从子查询定义新变量 - 只允许标量表达式。(SQL 服务器)

问题描述

我正在尝试将一列 [Missed 2x] 添加到现有表中,以指示主题是否有两个连续错过的日记。如果错过了最近的 2 篇日记,则值为“Missed 2x”,否则为 NULL。我编写了一个 select 语句(在下面的代码中),它成功地提取了符合此条件的 ID。当我创建一个用户定义的函数来交叉检查表并分配值时,它是站不住脚的,因为每次查询该表时都会为每个 ID 重新计算该函数并永远占用该函数。

我试图通过查看现有表的 ID 是否在子集表中来通过 Alter Table 分配值。我认为这应该可以节省资源,因为子集表只定义了一次,Alter 语句只是检查每个 ID 是否在子集中。然后我意识到我无法使用 Alter Table 执行此操作,因为我收到错误Subqueries are not allowed in this context。只允许标量表达式。

什么是最有效的替代方案?

ALTER TABLE [R3008_Subjchar] add [Missed 2x] as 
    case when [Subject ID] in 
        (
        select
        [Subject ID]
        from(
                select distinct 
                [Subject ID]
                , [Questionnaire Name]
                , [Task Date]
                , [Is Completed]
                , dense_rank () over (Partition by [Subject ID], [Questionnaire Name] order by [Task Date] desc) as recency
                from dbo.R3008_Questionnaire
                ) r
        where recency <=2
        group by [Subject ID]
        having count(case when [Is Completed] = 'no' and [Questionnaire Name] = 'FLU-PRO Questionnaire' then [Is Completed] end) = 2
        )
    then 'Missed 2x' end

标签: sqlsubquerycalculated-columnsalter-tablesql-view

解决方案


您不能在计算列中使用子查询;它只能访问当前行上的数据,不能访问其他行。

我认为存储此类信息不是一个好主意。相反,您可以创建一个视图;lag()可以方便地实现您想要的逻辑:

create view v_r3008_questionnaire
select q.*,
    case when [Is Completed] = 'no'
              and lag([Is Completed]) over(partition by [Subject ID], [Questionnaire Name] order by [Task Date]) = 'no'
        then 'Missed 2x'
    end as [Missed 2x]
from dbo.r3008_questionnaire

对于每个“失败”行,这将检查同一主题和问卷的先前状态是否也失败,并在这种情况下设置标志。


推荐阅读