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,
JOIN
sarang 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
users
alih-alih kata yang dicadangkan.user
-
Dengan asumsi bahwa
users.name
didefinisikan unik atau Anda dapat memiliki beberapa pengguna bernama 'luke'. -
Jika
(task.id, users.id)
disolved
didefinisikanUNIQUE
atauPRIMARY KEY
, Anda tidak perluDISTINCT
sama 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)
)