2017-12-28 7 views
0

Ich habe vier Tabellen:Auswahleinträge, die in einem von mehreren Tabellen referenziert werden

company 
id | name 

order 
number | company_id 

quote 
number | company_id 

invoice 
number | company_id 

ich die Liste der Unternehmen erhalten möchten, die in einem der drei (dh Bezug genommen wird, ausschließen Unternehmen, die nicht sind in irgendeiner).

Ich schrieb diese Anfrage:

select c.id, c.name from company c 
left outer join order o on o.company_id = c.id 
left outer join quote q on q.company_id = c.id 
left outer join invoice i on i.company_id = c.id 
where o.number is not null or q.number is not null or i.number is not null 

Aber die order, quote und invoice Tische sind recht groß. Die join bewirkt also, dass die Abfrage für immer ausgeführt wird (ein Join ist O (m * n), drei Joins ist O (m * n * p * q)).

Ich konnte diese Abfrage im Grunde drei Mal mit nur einer Verbindung bei jeder Abfrage (O (m * n) + O (m * p) + O (m * q)), aber ich hoffe auf mehr optimale Lösung.

Dies ist für Oracle

+0

Die Gefahr besteht darin, dass die drei Tabellen wahrscheinlich mehrere Zeilen pro Unternehmen enthalten. So könnte Unternehmen 1 5 Angebote, 2 Bestellungen und 2 Rechnungen für insgesamt 20 Zeilen (5 * 2 * 2) nur für diese eine Firma zurückgegeben haben. Es ist nicht die zugrundeliegende Größe der Tabellen, die die schlechte Leistung verursacht, sondern die Tatsache, dass das Unternehmen mehrmals in einem erscheint, und diese Duplikate werden dann auf nachfolgende Joins vergrößert. – Steve

+0

@Steve Richtig, das verstehe ich. Das wusste ich schon, bevor ich überhaupt die Abfrage geschrieben habe. Ich habe nur versucht, meine Herangehensweise an die Lösung zu zeigen, um zu verdeutlichen, warum ich feststeckte. – ryvantage

Antwort

2

zu einer Unterabfrage Join, die eine Vereinigung der Tabellen drei Ordnung tut:

SELECT 
    c.id, c.name 
FROM company c 
INNER JOIN 
(
    SELECT company_id FROM order 
    UNION 
    SELECT company_id FROM quote 
    UNION 
    SELECT company_id FROM invoice 
) t 
    ON c1.id = t.company_id 

Die union-Abfragen doppelte company_id entfernen automatisch sollen, so dass nur unterschiedliche Unternehmen, die vorhanden sind, in einer der drei Tabellen sollte in der Ergebnismenge dieser Unterabfrage sein. Die innere Verknüpfung filtert dann alle Firmen heraus, die überhaupt nicht vorhanden waren.

Verwandte Themen