Postgres SQL / HQL 查询结构比较 2 个列表

Postgres SQL / HQL query structure comparing 2 lists

我有一个 table 的 FridgeContents,一个 table 的食谱和一个 table 的 RecipeIngredients。

CREATE TABLE Recipes
(
  id bigserial NOT NULL,
  name text
);
CREATE TABLE Ingredients
(
  id bigserial NOT NULL,
  name text,
  description text
);
CREATE TABLE RecipeIngredients
(
  id bigserial NOT NULL,
  recipe_id bigint REFERENCES Recipes(id),
  ingredient_id bigint REFERENCES Ingredients(id),
  quantity numeric
);
CREATE TABLE FridgeContents
(
  id bigserial NOT NULL,
  ingredient_id bigint REFERENCES Ingredients(id),
  quantity numeric
);

我正在使用 Hibernate、Spring Data JPA 和 postgresql 数据库开发 SpringBoot 应用程序。

我正在尝试构建一个查询,该查询将return列出我可以根据当前配料制作的所有食谱。

一种方法是按顺序提取食谱的所有成分,从我的 FridgeContents 中检查它们,如果 RecipeIngredients 列表的其余部分为空,则 return true,但这听起来效率低下,尤其是如果我有 1000 种食谱。

这样的方法行得通吗?我可以使用更好的技巧吗?

Select * from Recipes where id in (
  Select distinct recipe_id from RecipeIngredients EXCEPT (
    Select distinct recipe_id from RecipeIngredients
    where ingredient_id NOT in (
      Select ingredient_id from FridgeContents
    )
  )
);

我会使用连接和聚合来解决这个问题:

select ri.recipe_id
from recipeingredients ri left join
     fridgecontents fc
     on ri.ingredient_id = fc.ingredient_id
group by recipe_id
having count(*) = count(fc.ingredient_id);

having 从句本质上是在说:食谱中的所有原料都在冰箱里。注意:如果冰箱或食谱可能有重复的成分,那么你应该使用:

having count(distinct ri.ingredient_id) = count(distinct fc.ingredient_id)

NOT EXISTS()关系除法结构。注意:结果还将包括完全没有配料的食谱 ...

SELECT * 
FROM recipes r
        -- ## You cannot make a recipe
WHERE NOT EXISTS (
        SELECT *
        FROM recipe_ingredients ri
        WHERE ri.recipe_id = r.id
        -- ## ... for which any of the ingredients
        -- ## ... is *NOT* available
        AND NOT EXISTS ( 
                SELECT * FROM fridgecontents fc
                WHERE fc.ingredient_id = ri.ingredient_id
                AND fc.quantity >= ri.quantity
                )
        );