Anda memiliki dua LEFT JOINS :
- Gabungan kiri pertama dapat bergabung ke beberapa baris dari
solved. Katakan, 'jane' dan 'luke' menyelesaikan tugas. - Gabungan kiri ke-2 hanya dapat bergabung dengan pengguna bernama 'luke' ('luke' dalam kondisi bergabung!).
Anda masih mendapatkan keduanya baris, 'jane' tidak ditampilkan, kondisi bergabung menyaringnya, tetapi LEFT JOINS mempertahankan baris dalam hasil dan menambahkan nilai NULL.
Anda dapat mencapai apa yang Anda cari dengan menggunakan tanda kurung dan [INNER] JOIN alih-alih LEFT JOINS antara solved dan users . Panduan:
Gunakan tanda kurung jika perlu untuk menentukan urutan bersarang. Jika tidak ada tanda kurung,
JOINsarang dari kiri ke kanan.
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;
-
Menggunakan nama tabel
usersalih-alih kata yang dicadangkan.user -
Dengan asumsi bahwa
users.namedidefinisikan unik atau Anda dapat memiliki beberapa pengguna bernama 'luke'. -
Jika
(task.id, users.id)disolveddidefinisikanUNIQUEatauPRIMARY KEY, Anda tidak perluDISTINCTsama sekali.
Kueri yang dihasilkan tidak hanya benar, tetapi juga lebih cepat.
Versi SqlAlchemy dari kueri di atas: (disumbangkan oleh @van)
Ini mengasumsikan bahwa Category , Task dan User adalah kelas yang dipetakan, sedangkan solved adalah turunan dari Table (hanya tabel asosiasi seperti yang ditunjukkan pada contoh kode Banyak ke Banyak):
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)
)