只有当子表中的记录与另一个子表

时间:2017-07-10 20:00:58

标签: mysql subquery

我有两组父/子表:

  1. referrals / modalities_match_referrals
  2. locations / modalities_match_providers
  3. 还有另一种表格形式,它是我们通常处理的所有形式的列表。

    对于任何推荐,我需要找到一个提供者列表(位置表),它可以执行推荐所需的每种方式。例如,如果转诊需要MRI和关节造影,那么该清单应限于那些既可以进行MRI也可以进行关节造影的人,即使这样的提供者提供除此转诊所需的其他方式之外的其他方式。

    我的问题:是否有一个查询(带子查询),只会生成一个列表,这些列表只包含那些可以通过modalities_match_referrals表执行与引荐相关联的所有模式的位置/提供者?

    当转介需要多种形式时,我的问题是过度包容。我的查询导致提供者列表至少可以执行其中一种模式,并且包括无法执行所有模态的提供者。

    以下是子/匹配表:

    CREATE TABLE modalities_match_referrals (
    id INT AUTO_INCREMENT PRIMARY KEY NOT NULL
    ,referral_id INT NOT NULL
    ,modality_id INT NOT NULL
    ,on_off TINYINT DEFAULT 0
    ,INDEX(referral_id)
    ,INDEX(modality_id)
    ,FOREIGN KEY(referral_id) REFERENCES referrals(id)
    ,FOREIGN KEY(modality_id) REFERENCES modalities(id)
    );
    
    CREATE TABLE modalities_match_providers (
    id INT AUTO_INCREMENT PRIMARY KEY NOT NULL
    ,location_id INT NOT NULL
    ,modality_id INT NOT NULL
    ,on_off TINYINT DEFAULT 0
    ,INDEX(location_id)
    ,INDEX(modality_id)
    ,FOREIGN KEY(location_id) REFERENCES locations(id)
    ,FOREIGN KEY(modality_id) REFERENCES modalities(id)
    );
    

    到目前为止我尝试了什么 我有一个很长的生产查询,这里包含的时间太长了,但我从这个较短的查询和子查询中得到了相同的提供者列表:

    SELECT locations.id AS 'Location ID'
    ,locations.name AS 'Provider'
    FROM locations
    JOIN (
        SELECT p.location_id
        FROM modalities_match_providers AS p
        RIGHT JOIN (
        SELECT modality_id
            FROM modalities_match_referrals
            WHERE on_off=1
            AND referral_id=9660        
        ) AS r ON r.modality_id = p.modality_id
        WHERE on_off=1
    ) AS l ON l.location_id=locations.id
    
    WHERE locations.recycle=0
    AND locations.locationstateid=1
    GROUP BY locations.id
    ORDER BY locations.name
    LIMIT 10;
    

    结果包括可以执行MRI和/或关节造影的提供者,我正在寻找的只是那些可以同时执行两者的提供者。

    过去,在推荐和位置表中作为列处理的模态。 sql非常简单,但是当引入新模式时,该系统的问题是在这些表中有列(这种情况发生的比你想象的要多 - 开放式核磁共振对抗站立核磁共振等)。

    我还想创建一个在while循环中调用的PHP类,它将列表呈现到网页上。该类将在modalities_match_referrals和modalities_match_providers之间进行比较,并返回true或false。根据返回值,将显示或不显示提供者。缺点是复杂性,我会担心页面的性能。

    提前感谢您提供任何帮助。

1 个答案:

答案 0 :(得分:0)

将引荐模式与位置交叉加入,以获得最佳结果。然后外部加入提供者的模式,看看实际覆盖了多少。使用GROUP BYHAVING获取缺乏模态的引荐/位置对。

select
  r.referral_id,
  l.id as location_id
from modalities_match_referrals r
cross join locations l
left outer join modalities_match_providers p
  on  p.referral_id = r.referral_id
  and p.modality_id = r.modality_id
  and p.location_id = l.id
group by r.referral_id, l.id
having count(*) = count(p.id)
order by r.referral_id, l.id;

这应该为所有可以执行所有模式的提供者提供所有推荐。