简体   繁体   English

查找仅包含纯素产品的所有食谱

[英]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:两条规则:

  1. A product is vegan, if one of its specific diets is 'VEGAN'.如果产品的特定饮食之一是“素食”,则该产品是纯素食的。
  2. A recipe is vegan, if it only consists of vegan products.食谱是纯素的,如果它只包含纯素产品。

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.在其他数据库中,如果您需要其他列,则可能需要同时列出SELECTGROUP 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM