我有两个表,我发现第二个表中存在缺失值,但第一个表中没有。
下面是我的sql代码。
SELECT DISTINCT A.Patient
,B.Visit
FROM ( SELECT Patient
,Visit
,VisitName
FROM dbo.PatientVisit
) A
,( SELECT Visit
,VisitName
FROM dbo.Visitlookup v1
) B
WHERE B.Visit NOT IN ( SELECT Visit
FROM dbo.PatientVisit p1
WHERE A.Patient = p1.Patient )
AND B.Visit <> A.Visit
GROUP BY A.Patient
,B.Visit
HAVING B.Visit <> MAX(A.Visit);
解释我的代码......
我有两个表用于患者就诊,另一个用于访问查找。我在10岁到70岁之间有耐心的访问。
有些患者在常规时间表中错过了访问。假设患者来过10,20,30,60和70次访问。所以40和50将会错过访问。
我想找回错过就诊的病人。所以我将患者和访问的患者数据作为查询A,将查询表中的数据作为查询B.然后我从查询表中查询表中访问,这将给我错过的访问次数。
代码工作正常,我想优化代码。当我检查执行计划时,我发现Hash Match占总体执行成本的46%。
以下是我的执行计划截图。
有没有办法优化此代码,以便性能更好?
我有sql fiddle中的架构和数据。
更新
我发现哈希匹配需要更多成本的原因。它的原因是
在以下情况下可能会弹出哈希匹配:
用户建议我创建约束并修改代码。
我在患者就诊表上创建了覆盖索引作为包含列,并对成本进行了一些更改。哈希匹配从46%降至20.5%,但排序操作的成本从26%降至37%。但整体成本降至41%
答案 0 :(得分:1)
我认为您不需要对表dbo.PatientVisit
和dbo.Visitlookup
进行子查询,cross join
也可以由INNER JOIN
替换。此外,您可以将NOT IN (SELECT FIELD FROM ... WHERE {Condition}))
替换为NOT EXISTS (SELECT NULL FROM ... WHERE {Condition})
。
所以,我建议最终必须是这样的:
SELECT A.Patient ,
B.Visit ,
MAX(A.Visit)
FROM dbo.PatientVisit AS A
INNER JOIN dbo.Visitlookup AS B ON NOT EXISTS ( SELECT NULL
FROM dbo.PatientVisit p1
WHERE A.Patient = p1.Patient
AND B.Visit = p1.Visit )
AND A.Visit <> B.Visit
GROUP BY A.Patient ,
B.visit
HAVING B.Visit <> MAX(A.Visit)
使用您的数据样本您将看不到差异,但如果您将多次增加数据集,您将看到此执行计划:
执行计划的SSMS反映:
SQL Sentry Plan Explorer执行计划的反映:
答案 1 :(得分:0)
您在查询计划的一个块上花费44%并不一定意味着查询速度很慢。但是,正如我所注意到的,您还有其他一些可能影响查询速度的问题。
您的表似乎没有正常化。您在VisitName
和Visitlookup
表中都有PatientVisit
。
您的表缺少主键,因此缺少任何索引。如果添加一些约束,则查询计划看起来非常不同。请参阅http://sqlfiddle.com/#!6/bb4db/1/0。
您正在使用float
类型而非某些整数类型来识别实体的字段。
查询本身看起来很可疑。您确定前两个子查询需要是子查询吗?