在CTE SQL Server 2008中声明变量

时间:2012-08-17 13:48:53

标签: sql sql-server tsql

我如何实现以下内容:

declare @myInt int
set @myInt=(select count(*) from x)
;with x as

(
select row_number() over(partition by c.patientid order by c.admissiondate) as rn
    ,c.patientid,c.admissiondate
    ,max(c.claimsfromdate)  as maxHemiDate
    ,min(c.claimsfromdate) minHemiDate  
    ,(
        select max(c2.claimsfromdate)
            from claims as c2
            where c2.patientid=c.patientid
            group by c2.patientid
     ) as maxClaimsDate

         ,p.drgCode
         ,datediff(dd,min(c.claimsfromdate),max(c.claimsfromdate)) /7 as weeksWithHemi
         from claims as c inner join icdclaims as ci on ci.id=c.id
         inner join tblicd as t on t.icd_id=ci.icd_id
         inner join patient as p on p.patientid=c.patientid
         and p.admissiondate = c.admissiondate
         and p.dischargedate = c.dischargedate
         where t.icdText like '%X%'  and p.statecode='21'
         group by c.patientid, c.admissiondate, p.drgCode
)

select p.patientid, count(*)
    from patient as p
    left join x on x.patientid=p.patientid
    where x.patientid is null
    group by p.patientid

执行此操作时抛出的错误是

  

无效的对象名称x

我有点认为,由于变量声明在CTE之外,所以会发生这种情况。如果我在WITH的括号内移动声明,我会收到另一个错误。

如何在CTE中分配这样的变量?或者你可以不使用从CTE中提取数据的变量吗?

5 个答案:

答案 0 :(得分:3)

要获取@myInt行数,您可以执行以下操作:

declare @myInt int
;with x as
(
   __your query__
)
select p.patientid, count(*)
    from patient as p
    left join x on x.patientid=p.patientid
    where x.patientid is null
    group by p.patientid


set @myInt=@@ROWCOUNT 

已编辑 (由于Jon Egerton评论)如果您需要计算x行,那么临时表就是这样:

declare @myInt int
;with x as
(
   __your query__
)
select * 
into #tmp_x
from x;

set @myInt=(select count(*) from #tmp_x)

select p.patientid, count(*)
    from patient as p
    left join #tmp_x x on x.patientid=p.patientid
    where x.patientid is null
    group by p.patientid

感谢Jon Egerton

答案 1 :(得分:3)

如果您使用的是SQL Server 2005或更高版本,则可以在每行上添加总计:

select t.*, cnt, count(*) over () as NumRows
from (select p.patientid, count(*) as cnt
      from patient as p left join
           x
           on x.patientid=p.patientid
      where x.patientid is null
      group by p.patientid
    ) t

如果您使用总计来计算百分比或类似的东西,那么在每一行上获得值可能会很方便。

答案 2 :(得分:2)

问题在于这一行:

set @myInt=(select count(*) from x)

您正在尝试在声明之前对x进行选择!

<强>更新

在这种情况下,最好使用临时表或表变量而不是CTE。例如:

declare @myInt int

select row_number() over(partition by c.patientid order by c.admissiondate) as rn
    ,c.patientid,c.admissiondate
    ,max(c.claimsfromdate)  as maxHemiDate
    ,min(c.claimsfromdate) minHemiDate  
    ,(
        select max(c2.claimsfromdate)
            from claims as c2
            where c2.patientid=c.patientid
            group by c2.patientid
     ) as maxClaimsDate

         ,p.drgCode
         ,datediff(dd,min(c.claimsfromdate),max(c.claimsfromdate)) /7 as weeksWithHemi
         INTO #XTable
         from claims as c inner join icdclaims as ci on ci.id=c.id
         inner join tblicd as t on t.icd_id=ci.icd_id
         inner join patient as p on p.patientid=c.patientid
         and p.admissiondate = c.admissiondate
         and p.dischargedate = c.dischargedate
         where t.icdText like '%X%'  and p.statecode='21'
         group by c.patientid, c.admissiondate, p.drgCode

set @myInt=(select count(*) from #XTable)

select p.patientid, count(*)
    from patient as p
    left join #XTable x on x.patientid=p.patientid
    where x.patientid is null
    group by p.patientid

这是一种快速而肮脏的方法,但您可以在脚本中更早地声明您的表。

答案 3 :(得分:2)

您不能将单个CTE用于两个不同的语句 - 它们超出范围。

因此,您需要删除对变量的需求,或者您只需声明一个表变量,然后根据需要继续选择该变量。

您可以按如下方式声明表格变换:

declare @x table (rowno int, patientid varchar...

然后,您可以使用您目前在CTE中获得的选择来填写该内容。

答案 4 :(得分:0)

CTE可以是复数。它并没有解决你所陈述的问题,但将复杂的CTE分解为几个步骤往往更加清晰,每个步骤都建立在先前的定义之上。在这个例子中,有一个递归CTE和第二个CTE,它根据第一个计算统计数据。最终SELECT结合了结果:

with CTE
  as (
    select 1 as Number
    union all
    select Number + 1
      from CTE
      where Number < 10
    ),
  Summary
  as (
    select Count( 42 ) as HowMany, Min( Number ) as Least, Max( Number ) as Most
      from CTE
    )
  select *
    from CTE cross join
      Summary