简体   繁体   中英

MySQL select rows from parent table only if records in child table match records in another child table

I have two sets of parent/child tables:

  1. referrals / modalities_match_referrals
  2. locations / modalities_match_providers

There is another table modalities which is a list of all of the modalities that we typically deal with.

For any referral, I need to find a list of providers (locations table) which can perform each of the modalities required by the referral. For example, if the referral requires an MRI and an arthrogram, the list of should be limited to those who can perform both an MRI and an arthrogram, even if such a provider offers other modalities besides the ones needed for this referral.

My question: is there a single query (with subqueries) that will result in a list of only those locations/providers who can perform all of the modalities linked to a referral through the modalities_match_referrals table?

My problem is one of over-inclusion when a referral requires more than one modality. My query is resulting in a list of providers than can perform at least one of the modalities and is including providers that are not able to perform all modalities.

Here are the child/matching tables:

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)
);

What I have tried so far I have a long production query which is too long to include here, but I am getting the same list of providers from this shorter query and subqueries:

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;

The results include providers that can perform MRIs and/or arthrograms, and what I am looking for are only those providers who can perform both.

In the past, the modalities where handled as columns in both the referrals and locations tables. The sql was a lot simpler but the issue with that system was having columns to those tables when a new modality was introduced (this happens more than you might think - open MRI vs stand up MRI, etc.)

I'm also thinking of creating a PHP class to be called during the while loop that renders the list onto the webpage. The class would do the comparing between modalities_match_referrals and modalities_match_providers and return true or false. Based on the return value, the provider would be displayed or not displayed. The downside there is complexity and I would be concerned about the performance of the page.

Thank you in advance for any help you can offer.

Cross join the referral modalities with the locations so as to get the optimal result. Then outer join the providers' modalities to see how much is actually covered. Use GROUP BY and HAVING the get the referral / location pairs that lack no modality.

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;

This should give you all referrals with all providers that can perform all their modalities.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM