一尘不染

将SQL WHERE IN转换为JOIN

sql

我有一个数据库,存储有关虚构人物的各种信息。有一张桌子上的人,具有一般信息,例如姓名,地址等,还有一些更具体的桌子,每个人都有健康史和接受过的教育。我现在想做的是,基于相似之处,例如在同一所学校同一时间,同一位医生或同一时间在同一家医院接受治疗,为一个人建立可能的联系。

遵循Query可以很好地解决此问题(:id是有问题的人的ID),但是它的速度非常慢(大约需要6秒钟才能得到结果)。

SELECT person.p_id as id, fname, lname, image FROM person WHERE 
                (person.p_id IN (
                    SELECT patient from health_case WHERE 
                        doctor IN (SELECT doctor FROM health_case WHERE patient =:id ) 
                        OR center IN (SELECT hc2.center FROM health_case as hc1, health_case as hc2 WHERE hc1.patient = :id AND hc2.center = hc1.center AND (hc1.start <= hc2.end AND hc1.end >= hc2.start)))
                OR person.p_id IN (
                    SELECT ed2.pupil FROM education as ed1, education as ed2 WHERE 
                        ed1.school IN (SELECT school FROM education WHERE pupil = :id) AND ed2.school = ed1.school AND (ed2.start <= ed1.end AND ed2.end >= ed1.start)
                )) 
                AND person.p_id != :id

将其转换为使用JOIN子句的最佳方法是什么?我似乎莫名其妙地无法解决这些问题…


阅读 217

收藏
2021-03-17

共1个答案

一尘不染

我想我了解您正在尝试做的事情。剥皮猫的方法有多种,但是我建议将查询分为两个单独的查询,然后用几个内部联接替换复杂的WHERE子句吗?因此,如下所示:

/* Find connections based on health care */
SELECT p2.p_id as id, p2.fname, p2.lname, p2.image
FROM person p
JOIN health_case hc on hc.patient = p.p_id
JOIN health_case hc2 on hc2.doctor = hc.doctor and hc2.healthcenter = hc.healthcenter and hc.start <= hc2.end and hc.end >= hc2.start and hc2.patient <> hc.patient
JOIN person p2 on p2.p_id = hc2.patient and p2.p_id <> p.p_id
WHERE p.p_id = :id

然后,创建一个单独的查询以基于教育获得联系:

/* Find connections based on education */
SELECT p2.p_id as id, p2.fname, p2.lname, p2.image
FROM person p
JOIN education e on e.pupil = p.p_id
JOIN education e2 on e2.school = e.school and e2.start <= e.end AND e2.end >= e.start and e.pupil <> e2.pupil
JOIN person p2 on p2.p_id = e2.pupil and p2.p_id <> p.p_id
WHERE p.p_id = :id

如果您确实希望合并数据结果,则可以使用,UNION因为两个查询都从人员表返回相同的列。

2021-03-17