HAVING子句SQL Server 2008中的派生表与相关子查询

时间:2012-10-25 15:05:22

标签: sql-server sql-server-2008 tsql

在这个例子中,我只有两张桌子,我正在工作。我正在检查哪些可能运行得更快,执行计划是相同的。这些查询的目的是找到与一个记录相关联的最小日期,该记录大于另一个记录的最大日期。第一个查询更简洁(尽管它不允许第二个查询的DATEDIFF列)。从长远来看,我觉得编写查询是第二种方式,性能更高,也许当我有很多连接时。是否有关于哪种方法的一般规则,或者是否是一个案例场景,你让优化器解决了吗?

第一

select c.patid,min(c.admitDate) as minDiabetesDate
    from clm_extract as c
    inner join icdClm as ic on ic.clmid=c.clmid
    where ic.icd like '250%' 
    group by c.patid
    having min(c.admitdate) > 
    (
        select MAX(c2.admitDate) as maxPreDiabetesDate
            from clm_extract as c2
            inner join icdClm as ic2 on ic2.clmid = c2.clmid
            where ic2.icd ='79029' and c2.patid=c.patid
            group by c2.patid
    )

第二

select distinct x.patid,x.minDiabetesDate,y.maxPreDiabetesDate 
from
(   

select c.patid, min(c.admitdate) as minDiabetesDate
    from clm_extract as c 
    inner join icdClm as ic on ic.clmid=c.clmid
    where ic.icd like '250%'
    group by c.patid
)x
inner join 
(
select c2.patid, MAX(c2.admitdate) as maxPreDiabetesDate
    from clm_extract as c2
    inner join icdClm as ic2 on ic2.clmid=c2.clmid
    where ic2.icd ='79029'
    group by c2.patid
)y on x.patid=y.patid
group by x.minDiabetesDate,y.maxPreDiabetesDate,x.patid
having DATEDIFF(dd,y.MaxPreDiabetesDate,x.minDiabetesDate) > 0

1 个答案:

答案 0 :(得分:4)

您已经观察到这两个查询具有相同的执行计划。这并不奇怪。 SQL是描述性语言,而不是过程语言。也就是说,语言描述了正在生成的内容,而不是生成它的方法。

当您使用子查询执行in语句或exists语句时, 正在执行连接。语法不同,但逻辑处理是相同的。这只是表达联接的另一种方式。引擎需要考虑一些差异。例如,一个“IN”正在子查询中使用隐​​式distinct进行内连接。

作为优先选择,我更喜欢第二个版本。我希望尽可能在from子句中提到的查询中使用表。

在考虑了您的查询之后,有一种更简单的方法来编写它:

select c.patid,
       min(case when ic.icd like '250%' then c.admitDate end) as minDiabetesDate,
       MAX(case when ic.icd = '79029' then c.admitDate end) as maxPreDiabetesDate
from clm_extract c
     inner join
     icdClm ic
     on ic.clmid=c.clmid
where ic.icd like '250%' or ic.icd = '79029' 
group by c.patid
having MAX(case when ic.icd = '79029' then c.admitDate end) <
       min(case when ic.icd like '250%' then c.admitDate end) 

这将case语句与聚合函数结合使用来计算所需的日期。顺便说一句,您在datediff子句中使用了having。对于简单的比较,这是不必要的。您可以使用“=”,“&lt;”等来比较日期。