Betrachten Sie unter SQL.
%Vor%Die Abfrage, wenn ich für meine Datenbank ausgeführt wird, gibt 85 Zeilen zurück. Nun, das ist nicht korrekt. Wenn ich nur den Teil "AND bvc_Order.OrderSource = 56" entferne, gibt es 5 Zeilen zurück, was wirklich korrekt ist. Seltsam..... Eine andere Sache, wenn ich das Teil entferne
%Vor%Es werden auch die 5 Zeilen wie erwartet zurückgegeben, selbst mit dem bvc_Order.OrderSource-Filter. Ich bin nicht sicher, warum es weitere Zeilen hinzufügt, während ich versuche, Zeilen zu reduzieren, indem Sie Filter verwenden.
Die Tabelle bvc_OrderItem_BundleItem enthält keine Zeilen für die Ergebnisreihenfolge ids oder OrderItemIDs
[Bearbeiten]
Danke, Leute, ich habe versucht, die LEFT / RIGHT Join Mix zu entfernen, aber der Query Manager erlaubt nicht nur LEFT, es fügt mindestens eine RIGHT Join hinzu. Ich habe das SQL aktualisiert, um zusätzliche Tabellen zu entfernen, und jetzt haben wir nur noch drei. Aber das gleiche Ergebnis
%Vor%[edit] Bisher gibt es dafür keine Lösung. Ich habe zuvor einen Link in meinem Kommentar mit Beispieldaten outout für gültige / ungültige Ergebnisse mit Abfragen eingefügt. hier ist es wieder. Ссылка
Eine Sache, an die Sie sich erinnern sollten, ist, dass ALLE Links nicht möglich sind. Lass mich das weiter erklären bvc_Order enthält den Hauptbestelldatensatz bvc_ORderItem enthält Bestellartikel / Produkte bvc_ORderItem_BundleItem enthält untergeordnete Produkte des Produkts, die in der Tabelle bvC_OrderItem verfügbar sind.
Jetzt NICHT Jedes Produkt hat untergeordnete Produkte, also hat bvc_OrderItem_BundleItem möglicherweise keinen Datensatz (und im aktuellen Szenario gibt es wirklich keine gültige Zeile für die Aufträge in bvC_OrderItem_BundleItem). Kurz gesagt, im aktuellen Szenario ist KEINE übereinstimmende Zeile in der Tabelle bvc_OrderItem_BundleItem verfügbar. Wenn ich diesen Join vorerst lösche, ist alles in Ordnung, aber in der Praxis kann ich den BundleItem-Table-Join nicht entfernen.
danke
Wenn Sie sagen
%Vor% wird als falsch ausgewertet, wenn bvc_Order.OrderSource
NULL
ist. Wenn der Join LEFT/RIGHT
fehlgeschlagen ist, wird NULL
angezeigt. Dadurch wird der Join LEFT/RIGHT
in einen inneren Join umgewandelt.
Sie sollten das Prädikat wahrscheinlich in die ON
-Klausel schreiben. Ein alternativer Ansatz, der möglicherweise nicht die gleichen Ergebnisse liefert, ist:
Die anderen Prädikate haben dasselbe Problem:
Eine andere Sache, wenn ich den Teil
OR bvc_OrderItem_BundleItem.ProductID IN ('28046_00')
lösche, werden auch die 5 Zeilen wie erwartet zurückgegeben
Wenn der Join fehlschlägt bvc_OrderItem_BundleItem.ProductID
ist NULL
.
Ich würde auch empfehlen, Abfragen manuell zu schreiben. Wenn ich Sie richtig verstehe, kommt diese Frage von einem Designer. Seine Struktur ist ziemlich verwirrend. Ich ziehe den wichtigsten Kommentar auf:
Das Mischen von linken und rechten äußeren Joins in einer Abfrage ist nur verwirrend. Sie sollten anfangen, indem Sie die from-Klausel umschreiben, um nur einen Typ zu verwenden (und ich empfehle dringend den linken äußeren Join). - Gordon Linoff
Wenn Sie das Unmögliche beseitigt haben, bleibt jedoch alles übrig unwahrscheinlich, muss die Wahrheit sein? S.H.
Es ist unmöglich, dass eine zusätzliche AND-Bedingung, die an eine WHERE-Klausel angehängt ist, jemals zu zusätzlichen Zeilen führen kann. Das würde einen Datenbank-Defekt bedeuten, von dem ich annehmen kann, dass er "unmöglich" ist. (Wenn nicht, dann denke ich, es ist wieder auf Platz eins).
Diese Tatsache erleichtert es, sich auf mögliche Gründe zu konzentrieren:
Wenn Sie auskommentieren
%Vor%Dann kommentieren Sie auch den Semikolon-Terminator aus. ist es möglich dass nach dieser Abfrage ein Text vorhanden ist, der sich auf die Abfrage auswirkt? Versuchen am Ende der vorherigen Zeile ein Semikolon setzen, um sicherzugehen.
Abhängig von dem Tool, mit dem Sie Abfragen ausführen, manchmal wenn a Abfrage wird nicht ausgeführt, das Tool zeigt fälschlicherweise eine alte Ergebnismenge an. Stellen Sie sicher, dass Ihre Abfrage ordnungsgemäß ausgeführt wird, indem Sie eine Dummy-Spalte hinzufügen zu der SELECT-Anweisung, um absolut zu beweisen, dass Sie live sehen Ergebnisse. Welches Werkzeug benutzen Sie?
Wenn Sie LEFT Outer Join verwenden, wird es alle Zeilen aus der linken Tabelle (dbo.bvc_OrderItem) geben, sobald Ihre Bedingungen erfüllt sind. Das Gleiche passiert mit der rechten äußeren Verbindung auch,
Diese Bedingungen (linker Join, rechter Join) dürfen die Zeilen nicht einschränken, da Zeilen aus einer Tabelle alle sein können, eine andere Tabelle nur aus einigen Zeilen.
überprüfen Sie mit Ihrer Join-Bedingung
Dann überprüfe deine Kondition:
(bvc_Order.StatusCode & lt; & gt; 1 UND bvc_Order.StatusCode & lt; & gt; 999)
wenn irgendwelche Zeilen diese Bedingung erfüllen
nächste Überprüfung mit einer anderen Bedingung
[bvc_OrderItem.ProductID IN ('28046_00')
ODER bvc_OrderItem_BundleItem.ProductID IN ('28046_00')]
Dann bvc_Order.OrderSource = 56
Vergleichen Sie das Ergebnis von drei Abfragen und überprüfen Sie die Daten mit den Bedingungen und dann schreiben Sie Ihre vollständige Abfrage, so dass Sie verstehen, wo der Fehler Sie getan haben.
Wenige Punkte, an die man sich erinnern kann 1.And wird während der virtuellen Join-Phasen angewendet 2. Wo die Klausel nach dem Endergebnis angewendet wird 3. Linker Join gefolgt von Right Join ist in einigen Fällen effektiv ein innerer Join
Lässt Ihre Anfrage Schritt für Schritt unterbrechen.
%Vor%Die obige Ausgabe ist eine einzelne virtuelle Tabelle (logisch), die alle Zeilen von b1 mit übereinstimmenden Zeilen von a1
enthältNun werden die Prädikate aus Ihrer und -Klausel angewendet
%Vor%was effektiv alle Zeilen von bvc_OrderItem_BundleItem entfernt, auch wenn sie Übereinstimmungen haben und das Ergebnis wie unten angezeigt wird, wenn bvc_OrderItem_BundleItem.ProductID IN ('28046_00') wahr ist
%Vor%Wenn diese Bedingung (bvc_OrderItem.ProductID IN ('28046_00')) wahr ist, dann fragen Sie sql, alle Zeilen in bvc_OrderItem zu ignorieren, was praktisch dasselbe Ergebnis wie oben bedeutet
%Vor%Als nächstes machst du den rechten Outer-Join mit dbo.bvc_Order, was sich für den Join-Punkt, den ich oben erwähnt habe, eignet.
Nehmen Sie an, Sie haben unter dem Ergebnissatz als Ausgabe, die alle bvc_order Tabelle (grobe Ausgabe nur für das Verständnis aufgrund des Mangels an tatsächlichen Daten) erhalten
%Vor%Als Nächstes werden AND-Prädikate angewendet
Statuscode & lt; & gt; 1 und Statuscode & lt; & gt; 999
bedeutet, dass Zeilen ignoriert werden, die mit bvc_order übereinstimmen und den Status 1, 999 haben, auch wenn sie übereinstimmende Zeilen gefunden haben
Als nächstes fragen Sie bvc_Order.OrderSource = 56; was bedeutet, dass ich mich nicht um andere Zeilen sorge, halte passende Zeilen nur für 56 und behalte den Rest als null
Ich hoffe, dies verdeutlicht, was Schritt für Schritt geschieht. Ein besserer Weg kann sein, einige Testdaten zur Verfügung zu stellen und die erwartete Ausgabe zu zeigen.
Sie können auch die physische Reihenfolge der Joins steuern, Sie können unten versuchen, um zu sehen, ob dies das ist, was Sie versuchen zu tun ..
%Vor%Es sieht so aus, als ob Sie den Abfrage-Designer verwenden. Ich würde vermeiden, dies zu verwenden, da dies Ihre Abfragen extrem verwirrend machen kann. Ihre Anfragen werden viel prägnanter sein, wenn Sie sie von Hand gestalten. Wenn Sie nicht vollständig verstehen, wie innere / äußere Verbindungen funktionieren, ist ein großes Lehrbuch, das ich selbst SQL beigebracht habe, Murachs SQL Server für Entwickler.
Nun zu der Antwort.
Ich habe darüber nachgedacht, wie Sie Ihr Problem lösen können, und wenn Sie versuchen, die Ergebnismenge auf 5 Zeilen zu reduzieren, warum verwenden Sie zuerst mehrere äußere Verknüpfungen? Ich würde in Erwägung ziehen, die Joins auf innere Joins statt auf äußere Joins umzustellen, wenn Sie nach einer sehr spezifischen Ergebnismenge suchen. Ich kann Ihnen wirklich keine wirklich umfassende Antwort geben, ohne genau zu betrachten, welche Ergebnisse Sie erreichen wollen, aber hier ist eine allgemeine Idee, die auf dem basiert, was Sie uns allen gegeben haben:
%Vor%Beginnen Sie hier und dann, basierend auf was Sie suchen, fügen Sie where-Klauseln hinzu, um Kriterien zu filtern.
Außerdem muss Ihre where-Klausel neu geschrieben werden, wenn Sie eine innere Verknüpfung anstelle einer äußeren Verknüpfung verwenden:
%Vor%Wenn Sie versuchen, Zeilen zu finden, die nicht in dieser Ergebnismenge enthalten sind, würde ich OUTER JOIN nach Bedarf verwenden (LINKS bevorzugt). Ohne weitere Informationen über das, was Sie in Ihrer Datenbank suchen, ist das das Beste, was wir alle tun können.
bLike @usr writ, der Grund für dieses unerwartete (für Sie) Ergebnis ist, dass Sie eine Abfrage mit Outer-Joins erstellen und Zeilen nach dem Join filtern. Wenn Sie Filterzeilen von äußeren verknüpften Tabellen benötigen, sollten Sie dies vor dem Join tun.
aber wahrscheinlich versuchst du das zu bauen:
Gibt diese Abfrage Ergebnisse, was Sie brauchen? Wenn nicht, versuchen Sie, die letzte Bedingung zu ändern, zum Beispiel:
%Vor%Sie können auch Bedingungen hinzufügen, um Bedingungen zu verbinden, zum Beispiel:
%Vor%ah, und wenn du immer bvc_Order mit bvc_OrderItem verbinden musst, dann benutze inner join
Tags und Links sql sql-server sql-server-2008