You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server Outer Apply聚合含外部引用报错及解决方案问询

SQL Outer Apply聚合外部引用报错的解决方案

场景说明

拥有people表,需查询人员是否在registry中及其首次加入registry的时间;另有visit表记录人员前往clinic(诊所)或hospital(医院)的就诊记录。需求为统计:

  • 人员加入registry前12个月内,各类型就诊的次数
  • 人员加入registry后,逐月累计的各类型就诊次数(假设就诊次数随时间递减)

问题与报错

最初使用Outer Apply编写SQL时触发以下错误:

Multiple columns are specified in an aggregated expression containing an outer reference. If an expression being aggregated contains an outer reference, then that outer reference must be the only column referenced in the expression.

尝试在Outer Apply内部关联外层的rgstry表时,又提示找不到该外部表。最终通过改用Left Join并在外层进行聚合的方式解决问题。

原始报错SQL

select
    people_table.person_id
    ,rgstry.start_dttm
    ,cast(datediff(day,rgstry.start_dttm,getdate())/30.0 as float) as MonthsSinceEnrollment
    ,coalesce(visits_12m.clinic_12m_Before,0) as clinic_12m_Before
    ,coalesce(visits_12m.hospital_12m_Before,0) as hospital_12m_Before
    ,coalesce(visits_12m.clinic_1m_after,0) as clinic_1m_after
    ,coalesce(visits_12m.hospital_1m_after,0) as hospital_1m_after
    ,coalesce(visits_12m.clinic_2m_after,0) as clinic_2m_after
    ,coalesce(visits_12m.hospital_2m_after,0) as hospital_2m_after
--... thru 12 months after

from people_table

join
    (
    select registry.person_id, registry.start_dttm
    from registry
    where
    registry.registry_id = 12345    --ROSTER
    and registry.registry_status = '1' --active
    ) as rgstry on people_table.person_id = rgstry.person_id

outer apply
    (
    select visits.person_id
    ,sum(case when visits.visit_dttm between dateadd(month,-12, rgstry.start_dttm) and rgstry.start_dttm and visits.visit_type = 'hospital' then 1 else 0 end) as clinic_12m_Before
    ,sum(case when visits.visit_dttm between dateadd(month,-12, rgstry.start_dttm) and rgstry.start_dttm and visits.visit_type = 'clinic' then 1 else 0 end) as hospital_12m_Before
    ,sum(case when visits.visit_dttm between rgstry.start_dttm and dateadd(month,1,rgstry.start_dttm) and visits.visit_type = 'hospital' then 1 else 0 end) as clinic_1m_After
    ,sum(case when visits.visit_dttm between rgstry.start_dttm and dateadd(month,1,rgstry.start_dttm) and visits.visit_type = 'clinic' then 1 else 0 end) as hospital_1m_After
    ,sum(case when visits.visit_dttm between rgstry.start_dttm and dateadd(month,2,rgstry.start_dttm) and visits.visit_type = 'hospital' then 1 else 0 end) as clinic_2m_After
    ,sum(case when visits.visit_dttm between rgstry.start_dttm and dateadd(month,2,rgstry.start_dttm) and visits.visit_type = 'clinic' then 1 else 0 end) as hospital_2m_After
    ,sum(case when visits.visit_dttm between rgstry.start_dttm and dateadd(month,3,rgstry.start_dttm) and visits.visit_type = 'hospital' then 1 else 0 end) as clinic_3m_After
    ,sum(case when visits.visit_dttm between rgstry.start_dttm and dateadd(month,3,rgstry.start_dttm) and visits.visit_type = 'clinic' then 1 else 0 end) as hospital_3m_After
    --... thru 12 months after

    from visits
    where
    people_table.person_id = visits.person_id
    and visits.visit_dttm >= dateadd(month,-12, rgstry.start_dttm) --get count of visits for preceding 12 months
    and visits.visit_dttm < dateadd(month,12, rgstry.start_dttm) --get count of visits 12 months following
    and visits.visit_type in
        (   
        'clinic'
        ,'hospital'         
        )
    group by visits.person_id
    ) as visits_12m

修正后的可行SQL

select
    people_table.person_id
    ,rgstry.start_dttm
    ,cast(datediff(day,rgstry.start_dttm,getdate())/30.0 as float) as MonthsSinceEnrollment
    ,sum(case when visits_12m.visit_type = 'clinic' and visits_12m.visit_dttm between dateadd(month,-12, rgstry.start_dttm) and rgstry.start_dttm then 1 else 0 end) as clinic_12m_Before
    ,sum(case when visits_12m.visit_type = 'hospital' and visits_12m.visit_dttm between dateadd(month,-12, rgstry.start_dttm) and rgstry.start_dttm then 1 else 0 end) as hospital_12m_Before
    ,sum(case when visits_12m.visit_type = 'clinic' and visits_12m.visit_dttm between rgstry.start_dttm and dateadd(month,1,rgstry.start_dttm) then 1 else 0 end) as clinic_1m_after
    ,sum(case when visits_12m.visit_type = 'hospital' and visits_12m.visit_dttm between rgstry.start_dttm and dateadd(month,1,rgstry.start_dttm) then 1 else 0 end) as hospital_1m_after
    ,sum(case when visits_12m.visit_type = 'clinic' and visits_12m.visit_dttm between rgstry.start_dttm and dateadd(month,2,rgstry.start_dttm) then 1 else 0 end) as clinic_2m_after
    ,sum(case when visits_12m.visit_type = 'hospital' and visits_12m.visit_dttm between rgstry.start_dttm and dateadd(month,2,rgstry.start_dttm) then 1 else 0 end) as hospital_2m_after
---.. thru 12 months after
from people_table

join
    (
    select registry.person_id, registry.start_dttm
    from registry
    where
    registry.registry_id = 12345    --ROSTER
    and registry.registry_status = '1' --active
    ) as rgstry on people_table.person_id = rgstry.person_id

left join
    (
    select visits.person_id,visits.visit_dttm ,visits.visit_type
    from visits
    where
    visits.visit_type in ('clinic','hospital')
    ) as visits_12m on people_table.person_id = visits_12m.person_id and datediff(month, rgstry.start_dttm, visits_12m.visit_dttm) between -12 and 12

group by
    people_table.person_id
    ,rgstry.start_dttm
    ,cast(datediff(day,rgstry.start_dttm,getdate())/30.0 as float)

内容的提问来源于stack exchange,提问作者jawz101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 14:30:04