Пропущенные объединения важны.Если вы посмотрите на полный запрос, то увидите, что Django выполняет два левых внешних соединения из таблицы foo
к соединительной таблице foo_bar
и к таблице bar
.
Рассмотрим два foos
и два bars
.Пусть foo_1
относится к bar_1
и bar_2
, а foo_2
не относится к каким-либо bars
.
В приведенном ниже запросе с двумя левыми внешними объединениями, по крайней мере, каждый foo
включаетодин раз, и NULL появится в столбце столбца для foo_2
, который не связан ни с одним bars
.
SELECT foo.id as foo_id, bar.id as bar_id
FROM foo LEFT OUTER JOIN foo_bar
ON foo_id = foo_bar.foo_id
LEFT OUTER JOIN bar
ON foo_bar.bar_id = bar.id;
+--------+--------+
| foo_id | bar_id |
+--------+--------+
| 1 | 1 |
| 1 | 2 |
| 2 | NULL |
+--------+--------+
Запрос для Foo.objects.get(bar__isnull=True)
похож на этот, но он не выбираетчто-нибудь из таблицы столбцов, и это фильтрует на bar.id
, равно NULL
, потому что нам нужны только foos
, которые не связаны с bars
.
SELECT foo.id as foo_id
FROM foo LEFT OUTER JOIN foo_bar
ON foo_id = foo_bar.foo_id
LEFT OUTER JOIN bar
ON foo_bar.bar_id = bar.id
where bar_id is NULL;
+--------+
| foo_id |
+--------+
| 2 |
+--------+