Je hebt twee LEFT JOINS
:
- De eerste linkse join kan deelnemen aan meerdere rijen van
solved
. Zeg, 'jane' en 'luke' hebben de taak opgelost. - De 2e linkse join kan alleen deelnemen aan gebruikers met de naam 'luke' ('luke' in de join-voorwaarde!).
Je krijgt nog steeds beide rijen, 'jane' wordt gewoon niet getoond, de join-voorwaarde filtert haar uit, maar de LEFT JOIN
behoudt de rij toch in het resultaat en voegt NULL-waarden toe.
U kunt bereiken wat u wilt door haakjes . te gebruiken en een [INNER] JOIN
in plaats van de LEFT JOIN
tussen solved
en users
. De handleiding:
Gebruik zo nodig haakjes om de volgorde van nesten te bepalen. In de afwezigheid van haakjes,
JOIN
s nest van links naar 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;
-
Tabelnaam
users
gebruiken in plaats van het gereserveerde woord.user
-
Ervan uitgaande dat
users.name
is gedefinieerd uniek of je kunt meerdere gebruikers hebben met de naam 'luke'. -
Als
(task.id, users.id)
insolved
is gedefinieerdUNIQUE
ofPRIMARY KEY
, je hebtDISTINCT
niet nodig helemaal niet.
De resulterende zoekopdracht is niet alleen correct, maar ook sneller.
SqlAlchemy-versie van de bovenstaande zoekopdracht: (bijgedragen door @van)
Dit veronderstelt dat Category
, Task
en User
zijn toegewezen klassen, terwijl solved
is instantie van Table
(alleen een associatietabel zoals getoond in codevoorbeeld Many to Many):
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)
)