[英]Find all recipes with just vegan products
I have been trying to find all recipes with just vegan products but so far I just have this:我一直试图找到所有纯素食产品的食谱,但到目前为止我只有这个:
SELECT DISTINCT r.*
FROM recipes r INNER JOIN recipe_product rp ON r.id = rp.recipe_id
INNER JOIN products p ON rp.product_id = p.id
INNER JOIN product_specificdiet ps ON p.id = ps.product_id
INNER JOIN specificdiets sd ON ps.specific_diet_id = sd.id
WHERE sd.type = 'VEGAN';
But that query is giving me all the products that are vegan for all the recipes.但是那个查询给了我所有食谱的素食产品。
No idea how could I resolve it.不知道我怎么能解决它。
Thanks!谢谢!
Two rules:两条规则:
In other words: A vegan recipe is a recipe for which NOT EXISTS
any product that is NOT IN
the set of vegan products.换句话说:一个素食主义者的食谱是食谱其
NOT EXISTS
任何产品,是NOT IN
设定的素食产品。
select *
from recipes r
where not exists
(
select null -- non-vegan ingredient
from recipe_product rp
where rp.recipe_id = r.id
and rp.product_id not in
(
select ps.product_id -- vegan product
from product_specificdiet ps
join specificdiets sd ON ps.specific_diet_id = sd.id
where sd.type = 'VEGAN'
)
);
SELECT
re.*
FROM
recipes re
WHERE
re.id NOT IN (
SELECT
r.id
FROM
recipes r
LEFT JOIN
recipe_product rp ON r.id = rp.recipe_id
LEFT JOIN
products p ON rp.product_id = p.id
LEFT JOIN
product_specificdiet ps ON p.id = ps.product_id
LEFT JOIN
specificdiets sd ON ps.specific_diet_id = sd.id
WHERE
ISNULL(sd.type, '') != 'VEGAN';
)
Use aggregation and a HAVING
clause:使用聚合和
HAVING
子句:
SELECT r.*
FROM recipes r JOIN
recipe_product rp
ON r.id = rp.recipe_id JOIN
products p
ON rp.product_id = p.id JOIN
product_specificdiet ps
ON p.id = ps.product_id JOIN
specificdiets sd
ON ps.specific_diet_id = sd.id
GROUP BY r.id
HAVING COUNT(*) FILTER (sd.type = 'VEGAN') = COUNT(*);
An alternative method would filter out ingredients that are not vegan and check for zero of them:另一种方法是过滤掉非素食的成分并检查其中的零:
HAVING COUNT(*) FILTER (sd.type <> 'VEGAN') = 0;
Postgres is one of the databases that allows you to specify SELECT r.*
even though you are only aggregating by r.id
-- because that is allowed when the aggregation key is a primary key. Postgres 是允许您指定
SELECT r.*
的数据库之一,即使您仅按r.id
聚合——因为当聚合键是主键时允许这样做。 In other databases, you may need to list the columns both in the SELECT
and the GROUP BY
if you want additional columns.在其他数据库中,如果您需要其他列,则可能需要同时列出
SELECT
和GROUP BY
列。
Maybe by joining to a sub-query.也许通过加入子查询。 One that uses a filters the specific diets that only uses vegan types.
使用过滤器过滤仅使用纯素食类型的特定饮食。
Untested notepad scribble :未经测试的记事本涂鸦:
SELECT r.*
FROM recipes r
JOIN
(
SELECT rp.recipe_id
FROM recipe_product rp
INNER JOIN products p
ON p.id = rp.product_id
INNER JOIN product_specificdiet ps
ON ps.product_id = p.id
LEFT JOIN specificdiets sd
ON sd.id = ps.specific_diet_id
GROUP BY rp.recipe_id
HAVING COUNT(CASE WHEN sd.type = 'VEGAN' THEN sd.id END) = COUNT(*)
) q
ON q.recipe_id = r.id;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.