Du har to LEFT JOINS
:
- Den 1. venstre joinforbindelse kan slutte sig til flere rækker fra
solved
. Sig, 'jane' og 'luke' løste opgaven. - Den 2. venstre deltagelse kan kun deltage for brugere ved navn 'luke' ('luke' i deltagelsestilstanden!).
Du får stadig begge dele rækker, 'jane' vises bare ikke, join-betingelsen filtrerer hende fra, men LEFT JOIN
bevarer rækken i resultatet alligevel og tilføjer NULL-værdier.
Du kan opnå det, du leder efter, ved at bruge parenteser og en [INNER] JOIN
i stedet for LEFT JOIN
mellem solved
og users
. Manualen:
Brug om nødvendigt parentes til at bestemme rækkefølgen af rede. I mangel af parentes, JOIN
s reden fra venstre mod højre.
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;
-
Brug af tabelnavn
users
i stedet for det reserverede ord.user
-
Forudsat at
users.name
er defineret unik eller du kan have flere brugere ved navn 'luke'. -
Hvis
(task.id, users.id)
isolved
er defineretUNIQUE
ellerPRIMARY KEY
, du behøver ikkeDISTINCT
overhovedet.
Den resulterende forespørgsel er ikke kun korrekt, men også hurtigere.
SqlAlchemy-version af ovenstående forespørgsel: (bidraget af @van)
Dette forudsætter, at Category
, Task
og User
er kortlagte klasser, mens solved
er forekomst af Table
(bare en associationstabel som vist i kodeeksempel Mange til Mange):
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)
)