LEFT JOIN 跨越三个表(带连接表)

Jor*_*Day 5 sql database postgresql many-to-many left-join

在 Postgres 中,有没有办法left join在由联结表链接的表之间执行 a ,并对链接表进行一些过滤?

比如说,我有两个表humanspets,我想在我有人类 ID 和宠物名称的地方执行查询。如果人类 ID 存在,但他们没有使用该名称的宠物,我仍然希望返回人类的行。

如果我从petsto有 FK 关系humans,这将起作用:

select h.*, p.*
from humans as h
left join pets as p on p.human_id = h.id and p.name = 'fluffy'
where h.id = 13
Run Code Online (Sandbox Code Playgroud)

我会得到一行 13 岁的人的详细信息和蓬松的价值观。此外,如果人类 13 没有名为“fluffy”的宠物,我会得到一行包含人类 13 的值,以及宠物列的空值。

但是,我没有直接的 FK 关系,我在humans和之间有一个连接表pets,所以我正在尝试这样的查询:

select h.*, p.*
from humans as h
left join humans_pets_junction as j on j.human_id = h.id
left join pets as p on j.pet_id = p.id and p.name = 'fluffy'
where h.id = 13
Run Code Online (Sandbox Code Playgroud)

它返回所有人类 13 的宠物的行,除了蓬松的行之外,还有空列。

如果我添加p.name = 'fluffy'WHERE子句中,这会过滤掉所有空行,但也意味着如果人类 13 根本没有名为 fluffy 的宠物,我会得到 0 行。

有没有办法复制 FK-style 的行为left join,但是当与连接表一起使用时?

Gor*_*off 4

一种方法是在子句中进行比较where

select h.*, p.*
from humans as h left join
     humans_pets_junction as j
     on j.human_id = h.id left join
     pets as p
     on j.pet_id = p.id and p.name = 'fluffy'
where h.id = 13 and (p.name = 'fluffy' or p.id is null);
Run Code Online (Sandbox Code Playgroud)

或者,将联结表和 pets 表作为子查询或 CTE 连接:

select h.*, p.*
from humans h left join
     (select j.*
      from humans_pets_junction j join
           pets p
           on j.pet_id = p.id and p.name = 'fluffy'
     ) pj
     on pj.human_id = h.id
where h.id = 13;
Run Code Online (Sandbox Code Playgroud)