我有三个表,第一个存储大洲,第二个存储默认存在的动物,第三个存储特定大洲和动物的第二个表中的例外。
大陆(最多3个,以简化结果)
| continent_code |
|----------------|
| EU |
| OC |
| AN |
animals_default_presence
| animal_id | animal | presence |
|-----------|------------|----------|
| 1 | dog | 1 |
| 2 | kangaroo | 0 |
| 3 | polar bear | 0 |
continent_animals_presence_exceptions
| continent_code | animal_id | presence |
|----------------|-----------|----------|
| OC | 2 | 1 |
| AN | 1 | 0 |
| AN | 3 | 1 |
结果是其中生活的所有大陆和动物的摘要:
| continent_code | animal_id |
|----------------|-----------|
| EU | 1 |
| OC | 1 |
| OC | 2 |
| AN | 3 |
我可以通过一个MySQL查询获得这样的结果吗?
答案 0 :(得分:1)
您可以使用union all
。我认为以下就是您所需要的:
select c.continent_code, adp.animal_id
from continent c cross join
animals_default_presence adp
where adp.presence = 1 and
(c.continent_code, adp.animal_id) not in
(select cape.continent_code, cape.animal_id
from continent_animals_presence_exceptions cape
where cape.presence = 0
)
union all
select cape.continent_code, cape.animal_id
from continent_animals_presence_exceptions cape
where cape.presence = 1;
Here是db <>小提琴。
答案 1 :(得分:0)
首先,您需要在动物和大洲之间做一个CROSS JOIN
,以获取它们的所有可能组合。现在,您可以根据动物和大陆对异常表进行LEFT JOIN
。
最终,可以使用稍微复杂的WHERE
条件来过滤出所需的结果集。我们要么考虑默认存在为1的那些行,要么没有例外;或者,考虑默认存在为0的那些行,但为它们定义一个例外。
SELECT c.continent_code,
cape.animal_id
FROM (SELECT c.continent_code,
a.animal_id,
a.presence AS default_presence
FROM animals_default_presence AS a
CROSS JOIN continents AS c
) AS all_combos
LEFT JOIN continent_animals_presence_exceptions AS cape
ON cape.continent_code = default_present_combos.continent_code
AND cape.animal_id = default_present_combos.animal_id
WHERE ( all_combos.default_presence = 1
AND ( cape.presence = 1
OR cape.presence IS NULL ) )
OR ( all_combos.default_presence = 0
AND cape.presence = 1 )
使用UNION ALL
的先前版本:
一种方法是利用UNION ALL
。在SELECT
查询之一中,您可以获取animal和continent_code的所有组合,其中animal的默认存在为 1 。但是,我们将需要使用LEFT JOIN .. WHERE .. IS NULL
进行“反加入”,以消除默认动物在特定大陆上的“存在”定义为 0 的例外情况。
在另一个SELECT
查询中,我们仅获取默认存在为 0 但在某些大洲中存在为 1 的动物的组合,按照例外中的定义。
SELECT
c.continent_code, cape.animal_id
FROM
(SELECT c.continent_code, a.animal_id
FROM animals_default_presence AS a
CROSS JOIN continents AS c
WHERE a.presence = 1) AS default_present_combos
LEFT JOIN continent_animals_presence_exceptions AS cape
ON cape.continent_code = default_present_combos.continent_code
AND cape.animal_id = default_present_combos.animal_id
AND cape.presence = 0
WHERE cape.animal_id IS NULL
UNION ALL
SELECT
cape.continent_code, cape.animal_id
FROM animals_default_presence AS a
JOIN continent_animals_presence_exceptions AS cape
ON cape.animal_id = a.animal_id
AND cape.presence = 1
WHERE a.presence = 0