2008-09-22 8 views
11

Ich habe zwei Tabellen mit Aufgaben und Notizen und möchte eine Liste von Aufgaben mit der Anzahl der zugehörigen Notizen für jeden abrufen. Diese beiden Abfragen die Arbeit machen:Transact-SQL - Unterabfrage oder Links-Join?

select t.TaskId, 
     (select count(n.TaskNoteId) from TaskNote n where n.TaskId = t.TaskId) 'Notes' 
from Task t 

-- or 
select t.TaskId, 
     count(n.TaskNoteId) 'Notes' 
from Task t 
left join 
     TaskNote n 
on  t.TaskId = n.TaskId 
group by t.TaskId

Gibt es einen Unterschied zwischen ihnen und sollte ich einen über den anderen verwenden, oder sind sie nur zwei Möglichkeiten, um die gleiche Arbeit tun? Vielen Dank.

Antwort

12

Bei kleinen Datensätzen sind sie waschbar, wenn es um die Leistung geht. Wenn indexiert, ist der LOJ ein wenig besser.

Ich habe in großen Datasets gefunden, dass ein innerer Join (ein innerer Join wird auch funktionieren.) Wird die Unterabfrage um einen sehr großen Faktor (sorry, keine Zahlen).

+0

dito auf dem inneren Join - ich habe gesehen, dass ein großer Unterschied auf großen Satz (vorausgesetzt, das ist das richtige Verhalten, das Sie wollen, und Sie müssen möglicherweise eine ISNULL() oder ähnliche Funktion) –

0

Sie können beide verwenden, und sie sind semantisch identisch. Im Allgemeinen besteht die Faustregel darin, die Form zu verwenden, die für Sie einfacher zu lesen ist, es sei denn, die Leistung ist ein Problem.

Wenn Leistung ein Problem ist, dann experimentieren Sie mit dem Umschreiben der Abfrage mit dem anderen Formular. Manchmal verwendet das Optimierungsprogramm einen Index für das eine Formular und nicht das andere.

1

Es gibt keine klare Antwort auf diese Frage. Sie sollten den SQL-Plan anzeigen. In Bezug auf die relationale Algebra sind sie im Wesentlichen gleichwertig.

6

In den meisten Fällen behandelt der Optimierer sie gleich.

Ich bevorzuge die zweite, weil es weniger Verschachtelung hat, die es einfacher zu lesen und einfacher zu warten macht. Ich habe begonnen, die gemeinsamen Tabellenausdrücke von SQL Server zu verwenden, um die Verschachtelung aus dem gleichen Grund zu reduzieren.

Zusätzlich ist die zweite Syntax flexibler, wenn es weitere Aggregate, die in der Zukunft zusätzlich zugegeben werden können, zu zählen, wie MIN (some_scalar), MAX(), AVG() usw.

2

Wenn Wenn Sie SQL Server Management Studio verwenden, können Sie beide Versionen in den Abfrage-Editor eingeben und dann mit der rechten Maustaste klicken und Geschätzten Ausführungsplan anzeigen auswählen. Sie erhalten zwei prozentuale Kosten für die Charge. Wenn sie dieselbe Zeit benötigen, werden sie beide zu 50% angezeigt - wählen Sie in diesem Fall aus anderen Gründen, was Sie bevorzugen (einfacher zu lesen, einfacher zu warten, besser mit Ihren Codierungsstandards usw.). Andernfalls können Sie den mit den niedrigeren prozentualen Kosten relativ zum Stapel auswählen.

Sie können die gleiche Technik verwenden, um jede Abfrage zu ändern, um die Leistung zu verbessern, indem Sie zwei Versionen vergleichen, die dasselbe tun.

Natürlich, weil es eine Kosten relativ zum Stapel ist, bedeutet es nicht, dass eine Abfrage so schnell ist, wie es sein könnte - es sagt Ihnen nur, wie sie miteinander vergleichen, nicht zu einer bestimmten optimalen Abfrage zu bekomme die gleichen Ergebnisse.

5

Die Unterabfrage wird langsamer ausgeführt, da sie für jede Zeile in der äußeren Abfrage ausgeführt wird. Der Join wird schneller sein als einmal. Ich glaube, dass der Abfrageoptimierer diesen Abfrageplan nicht umschreiben wird, da er die Äquivalenz nicht erkennen kann.

Normalerweise würden Sie einen Join und eine Gruppe für diese Art von Zählung durchführen. Korrelierte Unterabfragen der von Ihnen angezeigten Art sind hauptsächlich von Interesse, wenn sie eine Gruppierung oder ein komplexeres Prädikat für eine Tabelle ausführen müssen, die nicht an einer anderen Verknüpfung beteiligt ist.

1

Ich mache es zu einem Punkt, Unterabfragen wo immer möglich zu vermeiden. Die Verbindung wird in der Regel effizienter sein.