2016-06-15 9 views
1

Ich habe 2 Tische:Join SQL-Anweisungen Optimierung

Kunden

ID 
Customer_ID 
Name 
Sir_Name 
Phone 
Email 

und

Tabelle Rechnung

Manager_Name 
Manaer_First_Name 
Customer_ID1 
Customer_ID2 
Customer_ID3 

Es gibt nur eine Customer.Customer_IDCustomer_ID.Customer_ID mehrmals für jeden Kunden oder ein Kunde hat keinen Customer_ID

In Invoice.Customer_ID1 i die gleichen haben.

Ich mag alle Datensätze in Customer Table Join Invoice Table bekommen - prüfen, ob die Customer_ID = Customer_ID1 wenn nicht Customer_ID = Customer_ID2 Or Customer_ID = Customer_ID2

in überprüfen Wenn CUSTOMER_ID in einer der Zeilen gefunden wird, um die Suche zu beenden.

+0

geben Sie bitte Beispiel – Mahmoud

+0

Sie benötigen COALESCE() (und verbinden Sie die Kundentabelle dreimal) – wildplasser

+0

SQL ist eine _declarative_ Sprache, dh Sie können das System anweisen, welche Ergebnisse Sie wollen, und es entscheidet über die beste Weg, um die Daten zu erhalten .Wenn Sie also sagen "Wenn customer_ID in einer der Zeilen gefunden wird, stoppen Sie die Suche", ist dies nicht für SQL geeignet, da es bestimmt, wie _how_ die Daten erhält. Sie sollten also eine Abfrage schreiben, die sich darauf konzentriert, was Sie wollen, nicht wie Sie es bekommen. –

Antwort

0
select 
    * 
from [Table Invoice] A 
JOIN [Customer] B 
    ON B.Customer_ID = A.Customer_ID1 OR (B.Customer_ID <> A.Customer_ID1 AND B.Customer_ID = A.Customer_ID2) OR (B.Customer_ID = A.Customer_ID3 AND B.Customer_ID <> A.Customer_ID2 AND B.Customer_ID <> A.Customer_ID1) 

Dies würde Ihnen alle Rechnungen für alle Kunden zurückgeben. Wenn Sie Rechnungen nur für einen Kunden benötigen, fügen Sie

Anweisung hinzu. Wenn Sie nur eine, erste Rechnung benötigen, fügen Sie ‚TOP 1‘ Anweisung zur Auswahl:

SELECT TOP 1 
0

Könnte eine innere Verknüpfung auf oder Klausel

select Customer.*, Invocie.* 
from Customer 
inner join Invoice on (Customer.Customer_ID = Invoce.Customer_ID1 
    OR Customer.Customer_ID = Invoce.Customer_ID2 
    OR Customer.Customer_ID = Invoce.Customer_ID3) 
1

Wahrscheinlich der beste Weg, um die Abfrage zu schreiben ist:

select . . . 
from customer c join 
    invoice i 
    on c.customer_id = coalesce(i.customer_id1, i.customer_id2, i.customer_id3); 

Dies sollte in der Lage sein, einen Index auf customer(customer_id) zu nutzen. Ist dies nicht effizient ist, dann ist eine weitere Alternative left join:

select . . ., coalesce(c1.col1, c2.col1, c3.col1) as col1, . . . 
from invoice i left join 
    customer c1 
    on c1.customer_id = i.customer_id1 left join 
    customer c2 
    on c2.customer_id = i.customer_id2 left join 
    customer c3 
    on c3.customer_id = i.customer_id3; 

Der left join Vorteil eines Index auf customer(customer_id) nehmen. Sie müssen coalesce() in select verwenden, um das Feld aus der rechten Tabelle auszuwählen.

0

So verstehe ich Ihre Anfrage: Sie möchten alle Kunden, die mindestens einen Eintrag in der Rechnungstabelle haben. Aber pro Kunde möchten Sie nur den "besten" Rechnungsdatensatz haben; mit ID1 besser als ID2 und ID2 besser als ID3.

Verbinden Sie die Tabellen, um alle Übereinstimmungen zu erhalten, und ordnen Sie dann Ihre Übereinstimmungen mit row_number, die den am besten passenden Datensatz # 1 geben. Dann behalte nur diese Zeilen auf Platz # 1.

select * 
from 
(
    select 
    c.*, 
    i.*, 
    row_number() over 
    (
     partition by c.customer_id order by 
     case c.customer_id 
      when i.customer_id1 then 1 
      when i.customer_id2 then 2 
      when i.customer_id3 then 3 
     end 
    ) as rn 
    from customer c 
    join invoice i on c.customer_id in (i.customer_id1, i.customer_id2, i.customer_id3) 
) 
where rn = 1;