2017-07-10 6 views
0

ich zwei Sätze von Eltern/Kind-Tabellen haben:MySQL wählen Sie Zeilen aus übergeordneten Tabelle nur, wenn Datensätze in untergeordneten Tabelle übereinstimmen Datensätze in ein anderes Kind Tabelle

  1. Empfehlungen/modalities_match_referrals
  2. locations/modalities_match_providers

Es gibt eine andere Tabelle Modalitäten, die eine Liste aller Modalitäten ist, die wir normalerweise behandeln.

Für jede Überweisung muss ich eine Liste der Anbieter (Standorte Tabelle) finden, die jede der Modalitäten für die Verweisung erforderlich ausführen können. Wenn zum Beispiel die Überweisung eine MRT und ein Arthrogramm erfordert, sollte die Liste auf diejenigen beschränkt sein, die sowohl eine MRT als auch ein Arthrogramm durchführen können, auch wenn ein solcher Anbieter neben den für diese Überweisung erforderlichen auch andere Modalitäten anbietet.

Meine Frage: gibt es eine einzige Abfrage (mit Subqueries), die in einer Liste mit diesen Standorten/Anbietern führen, die alle von den Modalitäten im Zusammenhang mit einer Überweisung durch die modalities_match_referrals Tabelle durchführen können?

Mein Problem ist eine der über-Aufnahme, wenn ein Verweis mehr als eine Modalität erfordert. Meine Abfrage führt zu einer Liste von Anbietern, die mindestens eine der Modalitäten ausführen können, und schließt Anbieter ein, die nicht alle Modalitäten ausführen können.

Hier sind die Kind/passenden Tische:

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

Was ich bisher versucht Ich habe eine Abfrage lange Produktion, die zu lang ist hier zu enthalten, aber ich bin immer die gleiche Liste von Anbieter aus dieser kürzeren Abfrage und Unterabfragen:

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; 

Die Ergebnisse sind Anbieter, die MRTs und/oder Arthrogrammen durchführen kann, und was ich suche sind nur diejenigen Anbieter, die beide durchführen können.

In der Vergangenheit wurden die Modalitäten in den Tabellen für Verweise und Positionen als Spalten behandelt. Die SQL war viel einfacher, aber das Problem mit diesem System war Spalten zu diesen Tabellen, wenn eine neue Modalität eingeführt wurde (dies passiert mehr als Sie vielleicht denken - offene MRT gegen MRI, etc.)

Ich bin Ich denke auch daran, eine PHP-Klasse zu erstellen, die während der while-Schleife aufgerufen wird und die Liste auf der Webseite darstellt. Die Klasse würde den Vergleich zwischen modalities_match_referrals und modalities_match_providers durchführen und true oder false zurückgeben. Basierend auf dem Rückgabewert würde der Provider angezeigt oder nicht angezeigt. Der Nachteil dort ist Komplexität und ich wäre besorgt über die Leistung der Seite.

Vielen Dank im Voraus für jede Hilfe, die Sie anbieten können.

+1

HAVING COUNT (*) = 2 – Strawberry

+0

Vielen Dank. Das war peinlich einfach. – commodore64

Antwort

0

Kreuzen Sie die Referenzmodalitäten mit den Standorten an, um das optimale Ergebnis zu erhalten. Dann fügen Sie den Modalitäten der Anbieter hinzu, um zu sehen, wie viel tatsächlich abgedeckt ist. Verwenden Sie GROUP BY und HAVING die Verweis/Standort-Paare, die keine Modalität fehlt.

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; 

Dies sollte Ihnen alle Empfehlungen mit allen Anbietern, die alle ihre Modalitäten durchführen können.

+0

Danke, Thorsten! – commodore64

Verwandte Themen