Sie haben zwei LEFT JOINS
:
- Der 1. linke Join kann mit mehreren Zeilen von
solved
verknüpft werden . Sprich, 'jane' und 'luke' haben die Aufgabe gelöst. - Der 2. linke Beitritt kann nur mit Benutzern mit dem Namen „luke“ („luke“ in der Join-Bedingung!) verknüpft werden.
Sie erhalten immer noch beides Zeilen, 'jane' wird einfach nicht angezeigt, die Join-Bedingung filtert sie heraus, aber der LEFT JOIN
behält die Zeile im Ergebnis trotzdem bei und hängt NULL-Werte an.
Sie können erreichen, wonach Sie suchen, indem Sie Klammern verwenden und einen [INNER] JOIN
anstelle des LEFT JOIN
zwischen solved
und users
. Das Handbuch:
Verwenden Sie ggf. Klammern, um die Verschachtelungsreihenfolge festzulegen. Wenn keine Klammern vorhanden sind, JOIN
s Nest von links nach rechts.
SELECT c.name AS cat_name, t.name AS task_name, u.name AS user_name
FROM task t
JOIN category c ON cat.id = t.category_id
LEFT JOIN
(solved s JOIN users u ON u.id = s.user_id AND u.name = 'luke') ON s.task_id = t.id
ORDER BY 1, 2, 3;
-
Verwenden des Tabellennamens
users
anstelle des reservierten Wortes.user
-
Angenommen, dass
users.name
ist eindeutig definiert oder Sie können mehrere Benutzer mit dem Namen „luke“ haben. -
Wenn
(task.id, users.id)
insolved
istUNIQUE
definiert oderPRIMARY KEY
, brauchen SieDISTINCT
nicht überhaupt.
Die resultierende Abfrage ist nicht nur korrekt, sondern auch schneller.
SqlAlchemy-Version der obigen Abfrage: (Beigetragen von @van)
Dies setzt voraus, dass Category
, Task
und users
sind zugeordnete Klassen, während sie solved
werden ist eine Instanz von Table
(nur eine Assoziationstabelle, wie im Codebeispiel Many to Many gezeigt):
user_name = 'luke'
q = (session.query(Category.name, Task.name, User.name)
.select_from(Task)
.join(Category)
.outerjoin(
join(solved, User,
(solved.c.user_id == User.id) & (User.name == user_name),
))
.order_by(Category.name, Task.name, User.name)
)