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

Sql server SQL Server 2008 HAVING子句中的派生表与相关子查询,sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,在这个例子中,我只有两个工作表。我正在检查哪一个运行得更快,执行计划是否相同。这些查询的目的是查找与一条记录关联的最小日期,该日期大于另一条记录的最大日期。第一个查询更简洁,尽管它不允许第二个查询使用DATEDIFF列。从长远来看,我觉得用第二种方法编写查询的成本会更高,可能是在我有很多连接的情况下。关于哪种方法有什么一般性的规则吗?或者它是一个逐案的场景,然后由优化器来解决 首先 第二 select distinct x.patid,x.minDiabetesDate,y.maxPreDiab

在这个例子中,我只有两个工作表。我正在检查哪一个运行得更快,执行计划是否相同。这些查询的目的是查找与一条记录关联的最小日期,该日期大于另一条记录的最大日期。第一个查询更简洁,尽管它不允许第二个查询使用DATEDIFF列。从长远来看,我觉得用第二种方法编写查询的成本会更高,可能是在我有很多连接的情况下。关于哪种方法有什么一般性的规则吗?或者它是一个逐案的场景,然后由优化器来解决

首先

第二

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

您已经注意到这两个查询具有相同的执行计划。这并不奇怪。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语句和聚合函数来计算所需的日期。顺便说一下,您在having子句中使用了datediff。这对于简单的比较是不必要的。您可以使用=,您已经观察到这两个查询具有相同的执行计划。这并不奇怪。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语句和聚合函数来计算所需的日期。顺便说一下,您在having子句中使用了datediff。这对于简单的比较是不必要的。你可以只使用=,我喜欢这样使用最小值和最大值。我以前没想过。我喜欢这样使用最小值和最大值。我以前没想过。