如何避免在查询表时进行两次单独的传递?

时间:2013-09-16 20:44:12

标签: sql-server performance

这个问题的背景是医院就诊。逻辑有点复杂,但这些都是要求。

  • 表格访问包含患者的姓名和访问ID。
  • 表FilteredVisits包含符合某些条件的特定访问

报告在特定日期范围内运行 - 这很重要。我们假设2013年1月1日至2013年1月31日

  • 如果在该日期范围内FilteredVisits中存在访问,则 报告显示该访问的1。否则,它返回0.
  • 但是,如果在日期范围之前的FilteredVisits中存在该患者(Name1)的条目(2013年1月1日之前) 示例),然后所有该患者的访问需要为1, 无论FilterVisits表中是否存在其他访问。
  • PatientID和VisitID都是唯一值。
  • 报告仅在日期范围内输出患者和访问

请参阅下面的示例。

目前,代码正在对存储结果的临时表进行2次单独更新(2次传递)。一个更新将所选日期范围的值设置为0/1,然后另一个更新,其中搜索开始日期参数之前的所有内容。 FilteredVisits表可能很大,有没有办法优化它更快?

表1所有患者就诊

PatientNameID VisitID
-------------------

PatientName1 P1Visit1
PatientName1 P1Visit2
PatientName1 P1Visit3
PatientName2 P2Visit1
PatientName3 P3Visit1
PatientName3 P3Visit2

表2过滤访问

PatientNameID  VisitID  Date
-------------------------
PatientName1 P1Visit1    12/1/2012
PatientName1 P1Visit3    1/2/2013
PatientName3 P3Visit1    1/8/2013

结果:

Results
PatientName1 P1visit1   1
PatientName1 P1visit2   1 -- would be '0' but there was a visit by PatientName1 BEFORE the date range so set to 1
PatientName1 P1visit3   1
PatientName2 P2visit1   0
PatientName3 P3visit1   1
PatientName3 P3Visit2   0 -- this stays 0 because there is no entry of PatientName3 visit3 in table2 and no visit by PatientName3 prior to the selected date range

- 编辑:TempTable仅包括患者和所选日期范围的访问次数

-- First  pass
UPDATE t
SET MeasureIsTrue = 1
FROM TempTable t
INNER JOIN FilteredVisits fv ON fv.visitID = t.visitID 

-- Second pass      
UPDATE t
SET MeasureIsTrue = 1
FROM TempTable t
INNER JOIN FilteredVisits fv ON fv.PatientID = t.PatientID -- join on patientID to include all visits
        AND fv.visitDate < @BeginDate -- search only before date range

2 个答案:

答案 0 :(得分:3)

一次通过:

UPDATE t
SET MeasureIsTrue = 1
FROM TempTable t
INNER JOIN FilteredVisits fv ON
 (fv.PatientID = t.PatientID -- join on patientID to include all visits
    AND fv.visitDate < @BeginDate) -- search only before date range
 OR (fv.visitID = t.visitID)

虽然,在这种情况下,我不介意两次通过,因为它似乎不是性能问题,并且无论哪种方式都有效。由开发人员决定。

或者......你在找这个:

UPDATE t
SET MeasureIsTrue = 1
FROM TempTable t
INNER JOIN FilteredVisits fv ON fv.visitID = t.visitID
WHERE
 fv.PatientID = t.PatientID -- join on patientID to include all visits
    AND fv.visitDate < @BeginDate -- search only before date range

经过审核,我认为您正在寻找患者和访问表之间的LEFT JOIN,其中包含摘要信息。 SUM或COUNT,或者当一个例子,当VisitDate为NULL时,则为0,结束时为GROUP BY PatientName。

答案 1 :(得分:0)

UPDATE t
SET MeasureIsTrue = 1
FROM TempTable t
LEFT OUTER JOIN FilteredVisits fv1 ON fv1.visitID = t.visitID
LEFT OUTER JOIN FilteredVisits fv2 ON fv2.PatientID = t.PatientID
WHERE fv1.visitID is not null
   OR fv2.visitDate < @BeginDate -- search only before date range