Verbinden mehrerer Tabellen in SQL unter Begrenzung exponentieller Ergebnisse
Frage
Ich habe Google und Stack Overflow nach einer Antwort auf meine Anfrage durchsucht, aber ich habe das Gefühl, dass mein Mangel an SQL-Vokabular der Suche nach einer Antwort im Wege steht, da ich glaube, dass dies eine häufige Frage wäre.Alle hilfreichen Hinweise auf das, was ich lesen muss, sind immer willkommen.
Zur Frage: Ich versuche, drei Tabellen in Oracle 8i zu verknüpfen, z. B. eine Firmentabelle, eine Rechnungstabelle und eine Jobtabelle. Es besteht keine Verknüpfung zwischen der Rechnungstabelle und der Jobtabelle.Ich hoffe, dass ich in einer Abfrage alle drei Tabellen verknüpfen kann, die alle Rechnungen und alle Jobs für ein Unternehmen zurückgeben, ohne alle Jobs für jede Rechnung zurückzugeben (siehe meine Beispielergebnisse unten).
Ich will sehen:
Company 1 Invoice 1 Job 1
Company 1 Invoice 2 Job 2
Company 1 Invoice 3 Job 3
Ich will nicht sehen:
Company 1 Invoice 1 Job 1
Company 1 Invoice 1 Job 2
Company 1 Invoice 1 Job 3
Company 1 Invoice 2 Job 1
Company 1 Invoice 2 Job 2
Company 1 Invoice 2 Job 3
Company 1 Invoice 3 Job 1
Company 1 Invoice 3 Job 2
Company 1 Invoice 3 Job 3
Wie immer vielen Dank für jede Hilfe, die Sie anbieten können.
BEARBEITEN:
Im Wesentlichen haben sowohl die Rechnungs- als auch die Jobtabelle ein Firmentabellenschlüsselfeld, es ist nur so, dass die Job- und die Rechnungstabelle keine direkte Verknüpfung zueinander haben.Wenn die Instanz bei 2 Rechnungen und 3 Jobs angezeigt wird, möchte ich, dass sie idealerweise angezeigt wird und umgekehrt:
Company 1 Invoice 1 Job 1
Company 1 Invoice 2 Job 2
Company 1 Job 3
Obwohl ich das Problem so betrachte, habe ich das Gefühl, dass dies weiter von einer einfacheren Antwort entfernt ist, als ich gehofft hatte.
Lösung
Ihre Anforderung bedeutet, dass Sie ein Problem mit Ihrem Schema haben.Mein erster Rat in diesem Fall wäre, Ihr Schema zu ändern:fügen Sie ein job_id
zu invoice
oder ein invoice_id
zu job
(oder eine N-N-Beziehungstabelle invoice_job
).
Wenn Sie nicht bereit sind, Ihr Schema zu aktualisieren, können Sie eine Abfrage bearbeiten, die den Join ausführt.Der folgende Abfrage wird grundsätzlich beitreten job
und invoice
eins-zu-eins:
SELECT c.company_id, ij.job_id, ij.invoice_id
FROM company c
LEFT JOIN (SELECT job_id, invoice_id,
NVL(j.company_id, i.company_id) company_id
FROM (SELECT j.job_id, j.company_id,
row_number() OVER (PARTITION BY company_id
ORDER BY job_id) job_no
FROM job j) j
FULL OUTER JOIN
(SELECT i.invoice_id, i.company_id,
row_number() OVER (PARTITION BY company_id
ORDER BY invoice_id) invoice_no
FROM invoice i) i
ON j.company_id = i.company_id
AND j.job_no = i.invoice_no) ij
ON c.company_id = ij.company_id
Die Join-Bedingung ist hier künstlich.Wenn Sie eine Rechnung entfernen, kann sich die Beziehung zwischen Aufträgen und Rechnungen ändern.
Wenn die beiden Tabellen wirklich nichts miteinander zu tun haben, möchten Sie möglicherweise stattdessen die Ergebnisse anders anzeigen, beispielsweise:
SQL> SELECT cj.company_id, cj.jobs,
2 listagg(i.invoice_id, ',')
3 WITHIN GROUP (ORDER BY i.invoice_id) invoices
4 FROM (SELECT c.company_id,
5 listagg(j.job_id, ',') WITHIN GROUP (ORDER BY job_id) jobs
6 FROM company c LEFT JOIN job j ON c.company_id = j.company_id
7 GROUP BY c.company_id) cj
8 LEFT JOIN invoice i ON cj.company_id = i.company_id
9 GROUP BY cj.company_id, cj.jobs;
COMPANY_ID JOBS INVOICES
----------- ------ --------
1 1,2,3 1,2