Überprüfen Sie, ob sich einer der Werte in einem Unterabfrageergebnis befindet

8

Ich habe eine komplizierte Unterabfrage, die eine Liste von Auftrags-IDs zurückgibt. Ich brauche eine Liste der Kunden, die diese Bestellungen haben. Das Problem ist, dass es zwei Möglichkeiten gibt, einen Kunden einer Bestellung zuzuweisen (eines von zwei Feldern). Ich könnte einfach so etwas machen:

 select *
 from Customers
 where orderId in (select...) 
 or secondaryOrderId in (select ...)

Das Problem ist, dass die Unterabfrage enorm ist, sowohl in der Zeit, die für die Ausführung benötigt wird, als auch auf dem Bildschirm, den sie benötigt. Gibt es eine Möglichkeit zu überprüfen, ob eines der Felder eines der gewünschten Ergebnisse enthält?

user63844
quelle

Antworten:

10

Versuchen:

where exists (select * .... 
        where Customers.orderId = ... 
        or Customers.secondaryId = ...
     )

ZB wenn Sie vorhatten:

where orderId in (select value from ...)
or secondaryorderid in (select value from ...)

Dann machen Sie es so, dass Sie Ihre Unterabfrage nur einmal aufrufen und Ihre OR-Klausel darin einbauen.

 where exists (select * from ... 
        where Customers.orderId = value 
        or Customers.secondaryOrderId = value
     )

Der springende Punkt dabei ist, sicherzustellen, dass die komplizierte Unterabfrage nur einmal ausgeführt wird. Dies geschieht nicht mit einem CTE oder durch Ersetzen von zwei INs durch zwei EXISTSs.

Rob Farley
quelle
3

Ihre Abfrage sollte wahrscheinlich als existsanstelle von umgeschrieben werdenin

Weitere Beispiele finden Sie unter diesem Link .

Ihre Anfrage würde dann etwas in der Art von aussehen

select *
from Customers C
where exists (select 'x' from ordertable o where c.orderid = o.orderid) 
or exists (select 'x' from ordertable o where c.secondaryOrderId = o.orderid) 

Wenn beide Unterabfragen gleich sind, können Sie eine davon entfernen und wie folgt kombinieren

select *
from Customers C
where exists (select 'x' from ordertable o where c.orderid = o.orderid or c.secondaryOrderId = o.orderid) 
Tom V - versuchen Sie topanswers.xyz
quelle
2

Warum nicht eine Common Table Expression aka- withKlausel verwenden? Es ist genau für diesen Zweck (unter anderem) konzipiert.

with orderIds as (
  select orderId
  from ...
)
select *
from Customers
where orderId in (select orderId from orderIds) 
or secondaryOrderId in (select orderId from orderIds);

Die Dokumentation zu Microsoft finden Sie unter https://msdn.microsoft.com/en-us/library/ms175972%28v=sql.105%29.aspx .

Colin 't Hart
quelle
3
Nicht wirklich viel davon, wenn man dies in Bezug auf die benötigte Zeit tut. Der CTE wird nicht zwischengespeichert und beide Male ausgeführt, wenn auf ihn verwiesen wird. stackoverflow.com/questions/22041244/…
Mark Sinkinson
1
OK. Anscheinend behandelt jedes DBMS CTE anders.
Colin 't Hart
Ein CTE ist nicht für diesen Zweck ausgelegt. Es würde immer noch zweimal in die Hauptabfrage erweitert. Versuchen Sie und sehen Sie ...
Rob Farley
1
Und die Dokumentation von Microsoft ist irreführend: "[Ein CTE] kann als temporäre Ergebnismenge betrachtet werden", was ich so interpretierte, dass die Ergebnisse zwischengespeichert oder auf andere Weise wie eine temporäre Tabelle gespeichert werden. Jetzt gibt es eine andere T-SQL-Lösung, die noch nicht erwähnt wurde.
Colin 't Hart
@ Colin'tHart Willkommen in der Welt der Microsoft-Dokumentation :-)
Mark Sinkinson