Postgresql Select 具有值 X 或 Y 的关联记录不存在的行
Postgresql Select Rows where associated record with value X or Y does not exist
我有 3 张桌子:
Table columns
---------------------
items id, name
variations id, item_id
images id, variation_id, type
image
有一个 variation
而 variation
有一个 item
我想找到 items
没有 images
of type 4 or 5 (types are any integer 0 ..5 并且不能为 null)
下面的查询有效,但是它使用了 UNION 子查询
带有 NOT IN 约束,我认为这是低效的 - 问题是
因此,编写此查询的更有效方法是什么。
SELECT DISTINCT i.id, i.name
FROM items i
INNER JOIN variations v
ON v.item_id = i.id
INNER JOIN images vi
ON vi.variation_id = v.id
WHERE i.id NOT IN (SELECT i.id FROM items i
INNER JOIN variations v
ON v.item_id = i.id
INNER JOIN images vi
ON vi.variation_id = v.id
WHERE vi.type = 4
UNION
SELECT i.id FROM items i
INNER JOIN variations v
ON v.item_id = i.id
INNER JOIN images vi
ON vi.variation_id = v.id
WHERE vi.type = 5)
解决方案
根据 Gordons 下面的回答,最终解决方案是:
select i.*
from items i
where not exists (select 1
from variations v join
images im
on v.image_id = im.id
where v.item_id = i.item_id and i.type in (4, 5)
)
and exists (select 1
from variations v join
images im
on v.id = im.variation_id
where v.item_id = i.id)
I want to find items which don't have images of type 4 or 5
根据您的描述,这听起来像 not exists
:
select i.*
from items i
where not exists (select 1
from variations v join
images im
on v.image_id = im.id
where v.item_id = i.item_id and i.type in (4, 5)
);
Gordon 使用聚合的答案的替代方法:
SELECT DISTINCT
i.id,
i.name
FROM items i
INNER JOIN variations v
ON v.item_id = i.id
INNER JOIN images vi
ON vi.variation_id = v.id
GROUP BY
i.id
HAVING
COUNT(*) FILTER (WHERE vi.type IN (4, 5)) = 0;
请注意,上面假设 id
是 items
table 中的主键列。如果不是,那么也许我们应该改用 GROUP BY i.id, i.name
。
我有 3 张桌子:
Table columns
---------------------
items id, name
variations id, item_id
images id, variation_id, type
image
有一个 variation
而 variation
有一个 item
我想找到 items
没有 images
of type 4 or 5 (types are any integer 0 ..5 并且不能为 null)
下面的查询有效,但是它使用了 UNION 子查询 带有 NOT IN 约束,我认为这是低效的 - 问题是 因此,编写此查询的更有效方法是什么。
SELECT DISTINCT i.id, i.name
FROM items i
INNER JOIN variations v
ON v.item_id = i.id
INNER JOIN images vi
ON vi.variation_id = v.id
WHERE i.id NOT IN (SELECT i.id FROM items i
INNER JOIN variations v
ON v.item_id = i.id
INNER JOIN images vi
ON vi.variation_id = v.id
WHERE vi.type = 4
UNION
SELECT i.id FROM items i
INNER JOIN variations v
ON v.item_id = i.id
INNER JOIN images vi
ON vi.variation_id = v.id
WHERE vi.type = 5)
解决方案
根据 Gordons 下面的回答,最终解决方案是:
select i.*
from items i
where not exists (select 1
from variations v join
images im
on v.image_id = im.id
where v.item_id = i.item_id and i.type in (4, 5)
)
and exists (select 1
from variations v join
images im
on v.id = im.variation_id
where v.item_id = i.id)
I want to find items which don't have images of type 4 or 5
根据您的描述,这听起来像 not exists
:
select i.*
from items i
where not exists (select 1
from variations v join
images im
on v.image_id = im.id
where v.item_id = i.item_id and i.type in (4, 5)
);
Gordon 使用聚合的答案的替代方法:
SELECT DISTINCT
i.id,
i.name
FROM items i
INNER JOIN variations v
ON v.item_id = i.id
INNER JOIN images vi
ON vi.variation_id = v.id
GROUP BY
i.id
HAVING
COUNT(*) FILTER (WHERE vi.type IN (4, 5)) = 0;
请注意,上面假设 id
是 items
table 中的主键列。如果不是,那么也许我们应该改用 GROUP BY i.id, i.name
。