Mysql 将SQL WHERE IN转换为联接

Mysql 将SQL WHERE IN转换为联接,mysql,sql,Mysql,Sql,我有一个数据库,存储关于虚构人物的各种信息。有一个表格,上面有一般信息,如姓名、地址等,还有一些更具体的表格,上面有每个人的健康史和教育情况。 我现在想做的是,根据相似性为一个人建立可能的联系,比如同一时间在同一所学校,同一位医生,或者同一时间在同一家医院接受治疗 下面的查询可以很好地实现这一点:id是相关人员的id,但是它非常慢,大约需要6秒才能得到结果 SELECT person.p_id as id, fname, lname, image FROM person WHERE

我有一个数据库,存储关于虚构人物的各种信息。有一个表格,上面有一般信息,如姓名、地址等,还有一些更具体的表格,上面有每个人的健康史和教育情况。 我现在想做的是,根据相似性为一个人建立可能的联系,比如同一时间在同一所学校,同一位医生,或者同一时间在同一家医院接受治疗

下面的查询可以很好地实现这一点: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

将其转换为使用联接子句的最佳方法是什么?不知怎么的,我似乎无法理解这些…

我想我明白你想做什么。剥猫皮的方法不止一种,但我建议您将查询拆分为两个单独的查询,然后用两个内部联接替换复杂的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,因为两个查询都从person表返回相同的列。

取决于您的SQL引擎。具有合理查询优化器的较新SQL系统很可能会在同一个计划中重写和连接查询。通常,子查询IN子句使用联接重写

在可能没有强大查询优化器的简单SQL引擎中,联接应该更快,因为它们可能会在运行外部查询之前将子查询运行到内存中的临时表中


但是,在一些内存占用有限的SQL引擎中,子查询可能会更快,因为它不需要连接,从而生成更多的数据。

这应该可以工作,而且也很好,但要小心,在考虑重新构造架构之前,您的连接数即将达到大多数人建议的极限。感谢您提供有关架构结构的提示,@Z!经过一点测试后,我认为这是可行的,而且速度也非常快。拆分查询可能是对可能的连接进行分类的一个好主意。