【问题标题】:Should I find correct MySQL query or optimize database structure?我应该找到正确的 MySQL 查询还是优化数据库结构?
【发布时间】:2016-12-12 18:04:41
【问题描述】:

我有以下结构的数据库:

  • TABLE 成分(成分名称、颜色)

  • TABLE 食谱(recipe_name)

  • TABLE recipes_ingredients_parts(配方名称、成分名称、部分)

我想要的是获得与所选成分及其编号相对应的食谱。所以我首先尝试的是查询:

SELECT rr.* FROM 
  (SELECT r.* FROM receipes r 
    INNER JOIN receipes_ingredients_parts ri 
      ON r.receipe_name = ri.receipe_name 
        AND ri.ingredient_name = 'espresso' 
        AND ri.parts_number = '1') rr;

我得到的是 {"Americano", "Espresso"}。但这应该是“Espresso”,因为对于“Americano”应该有查询:

SELECT rr.* FROM 
 (SELECT r.* FROM receipes r 
   INNER JOIN receipes_ingredients_parts ri 
     ON r.receipe_name = ri.receipe_name 
       AND ri.ingredient_name = 'espresso' 
       AND ri.parts_number = '1') rr 
   INNER JOIN receipes_ingredients_parts ri 
     ON rr.receipe_name = ri.receipe_name 
       AND ri.ingredient_name = 'water' 
       AND ri.parts_number = '4';

接下来我的想法是更改配方表并为每种成分添加列以存储配方的数量。但它会接近 20 列这种类型。所以我很困惑,认为我的工作方式很糟糕。也许我应该为此目的使用一些好的查询?你们对所有的东西有什么想法吗?

【问题讨论】:

  • 添加 20 列不会“优化”您的数据库结构。您的第一个查询是获取任何以“浓缩咖啡”为成分的食谱;您是否希望它获得以“浓缩咖啡”为唯一成分的食谱? (如果是这样,this 可能就是您正在寻找的答案。)
  • 哦,是的,我想这也不太对;它为您提供包含列表中所有项目的事物,而不是事物仅包含列表中的项目。

标签: mysql


【解决方案1】:

我认为这就是您要查找的内容,它应该找到包含您列表中所有成分的receipe_names,并且没有其他成分。

SELECT receipe_name
, SUM(CASE 
      WHEN (ingredient_name, parts_number) IN (('espresso','1')) 
      THEN 1 ELSE 0 
      END
) AS matchedIngredients
, SUM(CASE 
      WHEN (ingredient_name, parts_number) NOT IN (('espresso','1')) 
      THEN 1 ELSE 0 
      END
) AS otherIngredients
FROM receipes_ingredients_parts
GROUP BY receipe_name 
HAVING matchedIngredients = 1 AND otherIngredients = 0

更通用的版本/模板:

SELECT aField
, SUM(CASE 
      WHEN someField IN ([matchList]) 
      THEN 1 
      ELSE 0 
      END
) AS matches
, SUM(CASE 
      WHEN someField NOT IN ([matchList]) 
      THEN 1 
      ELSE 0 
      END
) AS others
FROM aTable
GROUP BY aField
HAVING matches = [# of values in matchlist] 
   AND others = 0

或者,如果匹配列表中的项目可能在表中重复“aField”值:

SELECT aField
, COUNT(DISTINCT CASE 
      WHEN someField IN ([matchList]) 
      THEN someField
      ELSE NULL
      END
) AS matches
, COUNT(DISTINCT CASE 
      WHEN someField NOT IN ([matchList]) 
      THEN someField 
      ELSE NULL
      END
) AS others
FROM aTable
GROUP BY aField
HAVING matches = [# of values in matchlist] 
   AND others = 0

【讨论】:

  • 确实如此。工作完美。非常感谢。
  • 超级!这就是我在最后几分钟的想法(概括为 [matchList] 的方向))
  • @IgorChernega 作为一个小旁注,我应该提到以上假设成分-部分组合每个收据只有一次。
  • 或者没关系。这是为了 php query() 目的。我也将在这个意义上向脚本发布有效数据。无论如何,如果需要,我想可以推断出您分享的想法。再次感谢您的帮助)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
  • 2012-05-06
相关资源
最近更新 更多