首页 > 解决方案 > Postgresql 选择没有任何一组值的所有行

问题描述

我有一张叫 Meals 的桌子。膳食有许多成分(例如土豆泥、西兰花、牛排),并且每个成分都有_many 过敏原。

我想选择没有任何给定过敏原列表的膳食。

如果我加入这三个表,并且 allergen_id not in (... list of allergen ids),如果它有任何不在要排除的过敏原列表中的过敏原,那将返回我的饭菜,这是不对的:

select * from meals m 
join components c on c.meal_id=c.id 
join allergens a on a.component_id=c.id
where a.id not in (1,2,3,4)

如果一餐有过敏原 1 5 和 7,仍然会从上述查询中返回。怎么说“退还我所有不含以下任何过敏原的餐食”

更新澄清示例。

假设我有一顿由土豆泥、豌豆和馅饼组成的餐点。马什里面有奶制品,馅饼里面有麸质。然后我吃了一顿含有肉类过敏原的牛排餐(对素食主义者没有好处)。

土豆泥、豌豆、馅饼 -> 乳制品、麸质

牛排、薯条 -> 肉

我想选择不含奶制品的餐点。结果应该只是牛排/薯条餐。

如果我加入他们所有人:

select * from meals m 
join components c on c.meal_id=c.id 
join allergens a on a.component_id=c.id

这将使我为每种过敏原排上一排。因此,如果我添加 where 子句:

select * from meals m 
join components c on c.meal_id=c.id 
join allergens a on a.component_id=c.id
where a.id not in (2)

面筋将排成一排,因此不排除土豆泥/豌豆/馅饼餐。我该如何排除它?

标签: sqlpostgresqlpostgresql-10

解决方案


NOT EXISTS(...) 完全符合您的要求。

您自己的文本I want to select the meal(s) which doesn't have any of a given list of allergens.几乎可以直接翻译成 SQL:


 -- How do I say:
 -- Return me all meals
select * from meals m
where not exists ( --  which doesn't have 
        select * 
        from  components c  -- any of the following allergens
        join allergens a on a.component_id = c.id AND a.id in (1,2,3,4)
        where c.meal_id = m.id
        );

推荐阅读