【问题标题】:many-to-many select with complex condition条件复杂的多对多选择
【发布时间】:2014-05-24 11:32:28
【问题描述】:

我有桌子:

+------------+
| Ingredient |
+------------+
| id         |
+------------+
| name       |
+------------+

+---------------+
| Relingredient |
+---------------+
| id_ingredient |
+---------------+
| id_recipe     |
+---------------+

+--------+
| Recipe |
+--------+
| id     |
+--------+
| name   |
+--------+

并且我需要选择具有我想要的成分的食谱(所有成分都传递给他们)我试过这个:

SELECT R.id, R.nom FROM Recipe R, Relingredient RI, Ingredient I 
WHERE  R.id = RI.id_recipe AND RI.id_ingredient = I.id AND I.name='onion' AND I.name='oil' 
GROUP BY R.name

但返回零行

我也试过这个:

SELECT R.id, R.nom FROM Recipe R, Relingredient RI, Ingredient I 
WHERE  R.id = RI.id_recipe AND RI.id_ingredient = I.id AND (I.name='onion' or I.name='oil') 
GROUP BY R.name

但它会选择所有含有洋葱或油的食谱,而不仅仅是那些含有洋葱油的食谱......我该怎么办?

(编辑)我想要的示例:
例如我有食谱:
1:烤鸡(配料:鸡肉、洋葱、油)
2:中国汤(配料:猪肉,洋葱,油,面条)
3:蔬菜三明治(配料:面包、油、番茄、沙拉)
查询应该只返回食谱:烤鸡和中国汤

谢谢你帮助我!!

【问题讨论】:

    标签: sql select many-to-many


    【解决方案1】:

    试试这样的:

    SELECT
      R.id, R.name
    FROM Recipt R
      JOIN Relingredient RI
        ON R.Id = RI.Id_recipe
      JOIN Ingredient I
        ON RI.Id_ingredient = I.Id
    WHERE I.name = 'onion'
        OR I.name='oil'
    GROUP BY R.id, R.name
    HAVING COUNT(I.name) = 2
    

    【讨论】:

    • 它不起作用,但是谢谢,成分可能比我搜索的要多,我想选择包含我搜索的成分的食谱。
    • @user3671561 不行,这不是问题的解释。更加详细一些。此查询准确返回所有包含洋葱和油的食谱。
    • 它还返回给我一个只有油而不是油+洋葱的食谱
    • 谢谢先生!我又试了一次,它奏效了!不知道是上次我抄的不好还是怎么了,事实是现在很好用,我测试了很多次,感觉很好用
    • @MikeRamos,只有在您将油两次添加到配方中时才会出现这种情况。如果是选项,您可以使用 COUNT(DISTINCT I.Name) 代替。
    【解决方案2】:

    要准确获取您正在寻找的成分,请使用having 子句:

    SELECT R.id, R.nom
    FROM Recipe R JOIN
         Relingredient RI
         ON R.id = RI.id_recipe JOIN
         Ingredient I 
         ON RI.id_ingredient = I.id
    GROUP BY R.name
    HAVING SUM(CASE WHEN I.name = 'onion' THEN 1 ELSE 0 END) > 0 AND
           SUM(CASE WHEN I.name = 'oil' THEN 1 ELSE 0 END) > 0 AND
           SUM(CASE WHEN I.name NOT IN ('onion', 'oil') THEN 1 ELSE 0 END) = 0;
    

    having 子句中的每个条件都会检查其中一个条件。第一个检查至少一种成分是“洋葱”,第二个检查至少一种是“油”,第三个检查没有其他成分存在。如果要允许其他成分,请删除最后一个子句。

    这种方法对于成分的不同条件非常灵活。

    编辑:

    下面的having 子句只允许您将成分命名一次。但您还需要插入计数:

    HAVING COUNT(DISTINCT CASE WHEN I.name IN ('onion', 'oil') THEN I.name END) = COUNT(DISTINCT NAME) AND
           COUNT(DISTINCT NAME) = 2;
    

    distinct 是为了以防一个食谱可以包含不止一次的成分。

    【讨论】:

    • @HamletHakobyan 。 . .应该删除的行。谢谢。
    • 感谢您的宝贵时间,但似乎有些东西不起作用,它返回我:MySQL 返回了一个空结果集(即零行)。 (查询耗时 0.0028 秒)
    【解决方案3】:

    试试这个:

    SELECT R.id, R.name FROM Recipe R
           Where R.Id in (
                             Select RI.Id_recipe From Relingredient as RI 
                                    INNER JOIN Ingredient as I ON  RI.Id_ingredient = I.Id
                                    WHERE I.name = 'onion'
                                          OR I.name='oil'
                         )
    

    我完全明白了。 新查询:

    SELECT  *
            FROM    dbo.Recipt
            WHERE   Id IN ( SELECT  id_recipe
                FROM    dbo.Relingredient
                        INNER JOIN dbo.Ingredient ON id_ingredient = Id
                WHERE   Name = 'oil' )
        AND Id IN ( SELECT  id_recipe
                    FROM    dbo.Relingredient
                            INNER JOIN dbo.Ingredient ON id_ingredient = Id
                    WHERE   Name = 'union' )
    

    【讨论】:

    • 它不起作用,它返回给我的食谱有洋葱或油,而不是同时包含这两种成分的食谱,但无论如何谢谢。
    • 你能写一个示例数据来解释你想要什么吗?
    • 亲爱的迈克,我创建了您的示例,您的问题的答案不正确!!!!我的查询是正确的!!!
    猜你喜欢
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2013-01-11
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    相关资源
    最近更新 更多