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
)
);
我有一个 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
)
);