2017-02-10 2 views
0

Hier ist meine Tabellen Struktur:Wie kann ich einen bedingten Join machen?

// users 
+------+----------+ 
| id | name | 
+------+----------+ 
| 1 | Jack  | 
| 2 | Peter | 
| 3 | Ali  | 
| 4 | John  | 
+------+----------+ 

posts 
+----+-----------+-----------+---------------+-------------------------+ 
| id | author_id | editor_id |  title  |   content  | 
+----+-----------+-----------+---------------+-------------------------+ 
| 1 | 4   | null  | title1  | content1    | 
| 2 | 3   | null  | title2  | content2    | 
| 3 | 1   | 3   | title3  | content3    | 
| 4 | 3   | null  | title4  | content4    | 
| 5 | 2   | null  | title5  | content5    | 
| 6 | 2   | 1   | title6  | content6    | 
+----+-----------+-----------+---------------+--------------------------+ 

Alles, was ich bin versucht, Namen anstelle von IDs in der posts Tabelle zu tun ist, zu bekommen. Also hier ist meine Frage:

SELECT p.id, 
     p.title, 
     p.content, 
     u1.name AS author_name, 
     u2.name AS editor_name 
FROM posts 
LEFT JOIN users u1 ON p.author_id = u1.id 
LEFT JOIN users u2 ON p.editor_id = u2.id 
WHERE p.id = :post_id 

Ok alles in Ordnung. Was ist meine Frage? Wie Sie sehen, enthält editor_id in den meisten Fällen null. Also brauche ich keinen Beitritt (wenn sein Wert ist null). Ich meine Sekunde LEFT JOIN sollte in den meisten Fällen nicht auftreten. Ich möchte also eine Bedingung wie diese vor dem zweiten Join implementieren:

Wie kann ich das tun?

+0

Was ist Ihre Motivation dafür? Welchen Nutzen sehen Sie, den Sie bekommen? – Ray

+0

Es ist komplizierter als das. Wenn Sie den 2. linken Join entfernen, müssen Sie den 'u2.name AS editor_name' verlieren, da Sie kein' u2' mehr haben und die Abfrage fehlschlägt – RiggsFolly

+0

@Ray Meine Motivation ist die Vermeidung von Verschwendung. –

Antwort

0

Sie nicht das tun kann. Und das ist nicht nötig.

Der in der Frage p.editor_id <> null gezeigte bedingte Test wird garantiert, um zu NULL auszuwerten, also wird es nie WAHR sein. Aber selbst wenn wir das zu einem vernünftigeren p.editor_id IS NOT NULL ändern, gibt es immer noch keinen Sinn.

Es gibt bereits ein Gleichheitsprädikat, das u2.id sein gleichp.editor_id erfordert.

Das bedeutet, wenn p.editor_id NULL ist, dann ist es unmöglich, dass der Gleichheitsvergleich TRUE zurückgibt.

Es ist nicht so, als würde die Datenbank-Engine alle Zeilen der Benutzer durchkreuzen, um eine Zeile zu finden, von der sie bereits weiß, dass sie nicht existieren kann.

Also was ist der Sinn? Ich verstehe nicht, was Sie erreichen wollen.

Versuchen Sie, die zurückgegebene Ergebnismenge zu beeinflussen (um etwas anderes zu erhalten) oder die Leistung zu verbessern, oder was?


Es wäre gültig, dies zu ändern:

LEFT JOIN users u2 ON p.editor_id = u2.id 

Um dies:

LEFT JOIN users u2 ON p.editor_id = u2.id AND p.editor_id IS NOT NULL 

aber fügte hinzu, dass Zustand nichts ändert. Es ist überflüssig. Die p.editor_id = u2.id überprüft bereits, dass p.editor_id nicht null ist; Wenn es null ist, ist es nicht möglich, dass es gleich u2.id ist. (NULL ist nie "gleich" zu irgendetwas.)

+0

Ja genau ich versuche die Leistung zu verbessern ..! Mit anderen Worten, meine Motivation ist die Vermeidung von Abfallverarbeitung. –

+0

@MartinAJ: Wenn es Ihr Ziel ist, die Leistung zu verbessern, dann schauen Sie sich die Ausgabe von 'EXPLAIN' an. Dadurch können Sie den Ausführungsplan, den Satz von Operationen, die MySQL ausführt, und die Indizes, die zur Erfüllung der Abfrage verwendet werden, sehen. (Durch den Vergleich von EXPLAIN mit der ursprünglichen Abfrage und einer modifizierten Abfrage wird ersichtlich, ob diese Änderungen den Ausführungsplan beeinflussen. Oft kann MySQL durch das Erstellen geeigneter Indizes eine effizientere Menge von Operationen ausführen. Wenn Sie EXPLAIN nach dem Hinzufügen eines Index ausführen, wird angezeigt, ob a neuer Index wird verwendet. – spencer7593

1

Das glaube ich nicht, dass Sie die NOT NULL Bedingung angeben müssen, ist, dass die Art und Weise LEFT JOIN funktionieren würde (unabhängig davon, ob Sie Ihr Ziel erreichen oder nicht)

2

Kurze Antwort: Nicht möglich.

Warum:

  • Das Wesen eines LEFT JOIN an sich ist ein bedingter. Sie enthält alle Datensätze aus der Tabelle "Linke Seite" und füllt Werte, die von rechts übereinstimmen, andernfalls liefert sie Nullen, wenn basierend auf der Join-Bedingung keine Übereinstimmung gefunden wird.
  • Eine bedingte Funktionalität, wie Sie sie in SQL beschreiben, könnte eine fehlerhafte Abfrage erzeugen. Sie können nicht einfach ein ganzes Produkt von Join aus einer Abfrage nehmen, das ist besonders offensichtlich, wenn die Ergebnisse an anderer Stelle (wie in den Auswahlparametern) verwendet werden.

Was Sie versuchen zu tun ist unnötig und würde keinen zusätzlichen Nutzen bieten.

1

Wenn Sie sehr wenige editor_id wirklich vorhanden haben, können Sie korrelierte Unterabfrage in der Auswahl verwenden, um den Namen des Editors zu erhalten.

SELECT p.id, 
     p.title, 
     p.content, 
     u1.name AS author_name, 
     (select name from users u where u.id = p.editor_id) as editor_name 
FROM posts p 
LEFT JOIN users u1 ON p.author_id = u1.id 
WHERE p.id = :post_id 
Verwandte Themen