[英]How to filter a many-to-many left join using the rightmost table?
Suppose I have the following tables:假设我有以下表格:
Machine机器
| id | name |
+----+---------+
| 1 | Blender |
| 2 | Slicer |
| 3 | Masher |
Part部分
| id | name | instock |
+----+-----------------+---------+
| 1 | Blade | 5 |
| 2 | Rotating engine | 0 |
| 3 | Plug | 10 |
| 4 | Wire | 10 |
MachinePart (many-to-many) MachinePart (多对多)
| mid | pid |
+-----+-----+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 3 |
| 2 | 4 |
I want a single query to list all machines with parts (outer joined), as long as the part is in stock .我想要一个查询来列出所有带有零件(外连接)的机器,只要零件有库存。
I have tried doing the condition in the LEFT JOIN, but then the middle table generates an unwanted record:我尝试在 LEFT JOIN 中执行条件,但中间表生成了不需要的记录:
SELECT m.id, m.name, mp.pid, p.name, p.instock
FROM machine m
LEFT JOIN machinepart mp ON mp.mid = m.id
LEFT JOIN part p ON p.id = mp.pid AND instock > 0
| id | name | pid | name | instock |
+----+---------+------+-------+---------+
| 1 | Blender | 1 | Blade | 5 |
| 1 | Blender | 2 | NULL | NULL | -> I don't want this record
| 1 | Blender | 3 | Plug | 10 |
| 1 | Blender | 4 | Wire | 10 |
| 2 | Slicer | 1 | Blade | 5 |
| 2 | Slicer | 3 | Plug | 10 |
| 2 | Slicer | 4 | Wire | 10 |
| 3 | Masher | NULL | NULL | NULL | -> But good, I want this record
How do I filter machinepart
based on a field in the related table part
?如何根据相关表
part
中的字段过滤machinepart
?
If it matters, I'm using PostgreSQL.如果重要的话,我正在使用 PostgreSQL。 (but I assume the solution will be generic)
(但我认为解决方案将是通用的)
WHERE P.INSTOCK IS NOT NULL
You can also get all of the "out of stock" parts with IS NULL
instead您也可以使用
IS NULL
来获取所有“缺货”零件
edit: I didn't see you DO want results for machines with no parts (because neither "part is out of stock" nor "part is in stock" make sense for a machine with no parts?)编辑:我没有看到您确实想要没有零件的机器的结果(因为“零件缺货”或“零件有货”对于没有零件的机器都没有意义?)
WHERE P.INSTOCK IS NOT NULL
OR MP.PID IS NULL
edit2: <2nd suggestion won't work either> edit2:<第二个建议也不起作用>
I think you want an INNER JOIN
and then a LEFT JOIN
:我想你想要一个
INNER JOIN
然后一个LEFT JOIN
:
SELECT m.id, m.name, mp.pid, p.name, p.instock
FROM machine m INNER JOIN
machinepart mp
ON mp.mid = m.id LEFT JOIN
part p
ON p.id = mp.pid AND p.instock > 0;
EDIT:编辑:
This produces the results that you request:这会产生您要求的结果:
SELECT m.id, m.name, mp.pid, p.name, p.instock
FROM machine m LEFT JOIN
machinepart mp
ON mp.mid = m.id LEFT JOIN
part p
ON p.id = mp.pid
WHERE (p.instock > 0 OR p.instock IS NULL);
Here is a db<>fiddle. 这是一个 db<>fiddle。
Seems like unusual logic, though.不过,这似乎是不寻常的逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.