2009-03-02 85 views
1

我有这个查询是很长的,但添加一个where子句,或加入一个字符串使它需要额外的2秒运行。我无法弄清楚为什么。加入varchar(50)外键减慢查询

下面是完整的查询:

inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd' 

此外,它移动到where条款具有相同的效果:

where p.dosing = 'da_ncd' 

ALTER PROCEDURE [dbo].[RespondersByPracticeID] 
    @practiceID int = null, 
    @activeOnly bit = 1 
AS 
BEGIN 
    SET NOCOUNT ON; 
    select 
     isnull(sum(isResponder),0) as [Responders] 
     ,isnull(count(*) - sum(isResponder),0) as [NonResponders] 
     ,isnull((select 
       count(p.patientID) 
      from patient p 
       inner join practice on practice.practiceid = p.practiceid 
          inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd' 
       where 
       p.practiceID = isnull(@practiceID, p.practiceID) 
       and p.active = case @activeOnly when 1 then 1 else p.active end 
      ) - (isnull(sum(isResponder),0) + isnull(count(*) - sum(isResponder),0)),0) 
     as [Undetermined] 
    from ( 
     select 
      v.patientID 
      ,firstVisit.hbLevel as startHb 
      ,maxHbVisit.hblevel as maxHb 
      , case when (maxHbVisit.hblevel - firstVisit.hbLevel >= 1) then 1 else 0 end as isResponder 
      ,count(v.patientID) as patientCount 
     from patient p 
      inner join visit v on v.patientid = v.patientid 
      inner join practice on practice.practiceid = p.practiceid 
      inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd' 
      inner join (
       SELECT 
        p.PatientID 
        ,v.VisitID 
        ,v.hblevel 
        ,v.VisitDate 
       FROM Patient p 
        INNER JOIN Visit v ON p.PatientID = v.PatientID 
       WHERE 
        v.VisitDate = (
         SELECT MIN(VisitDate) 
         FROM Visit 
         WHERE PatientId = p.PatientId 
        ) 
      ) firstVisit on firstVisit.patientID = v.patientID 
      inner join (
       select 
        p.patientID 
        ,max(v.hbLevel) as hblevel 
       from Patient p 
        INNER JOIN Visit v ON p.PatientID = v.PatientID 
       group by 
        p.patientID 
      ) MaxHbVisit on maxHbVisit.patientid = v.patientId 
     where 
      p.practiceID = isnull(@practiceID, p.practiceID) 
      and p.active = case @activeOnly when 1 then 1 else p.active end 

     group by 
      v.patientID 
      ,firstVisit.hbLevel 
      ,maxHbVisit.hblevel 
     having 
      datediff(
       d, 
       dateadd(
        day 
        ,-DatePart(
         dw 
         ,min(v.visitDate) 
        ) + 1 
        ,min(v.visitDate) 
       ) 
       , max(v.visitDate) 
      ) >= (7 * 8) -- Eight weeks. 
    ) responders 
END 

减慢下来是线

否则,查询几乎立即运行。 >.<

+0

is l.lookupid索引? – sfossen 2009-03-02 20:26:06

+0

是的,它的主键 – Shawn 2009-03-02 20:26:27

回答

2

啊,对不起,我想通了。 Patient.Dosing被设置为允许空值。我想这是一种不同的索引。

0

尝试在该表上创建一个索引,并确保在该字段列表中正确包含该VARCHAR字段。

2

为了记录,即使问题得到解答。 通常情况下会发生这种情况,因为执行计划已更改。比较查询分析器中的计划。

2

另一个问题是数据类型 - 如果p.dosing和l.lookupid不同 - 例如,nvarchar与varchar可能会产生巨大影响。