【问题标题】:Database Design, is my database rational correct? one Primary key to Multiple foreign keys?数据库设计,我的数据库合理吗?一个主键到多个外键?
【发布时间】:2012-12-29 14:23:43
【问题描述】:

我有一个想法,我想要执行,但在涉及表之间的关系时,我的数据库设计非常生疏。我希望能够在 3 个<input type="text"> 字段中输入 3 种成分,然后搜索所有包含这些成分的食谱。

我有 3 张桌子...

  • 成分
  • 食谱
  • 菜单

粗体的列是我的主键,我希望斜体的列是外键。

示例 - iName 是 iName1 iName2 和 iName3 的主键。


成分

iName - iType

食谱

mName - iName1 - iName2 - iName3 - 方法

菜单

mName - mDiscription - 过敏


我的问题是……我的表之间的关系是否足够有效,可以满足我的需求?例如,如果我想加入查询会是什么

SELECT mName, mDiscripton, mAllergy
FROM menu
WHERE iName1 = input etc etc

任何关于该主题的说明都会有很大帮助,我已经有一个表版本的数据库并且我使用的查询工作正常,我只想重新设计我的数据库并修改我的查询以适应。

【问题讨论】:

  • 拼写:mDiscripton 应该是 mDescription,而且现在一般不使用列 (imo) 中的表前缀,混合大小写也不会使用。 menu.description 好多了。

标签: mysql database one-to-many rationale


【解决方案1】:

请不要使用 1..n 列来保存两个表之间的 n..m 连接。

由于您可以在不同的食谱中使用一种成分,因此您需要一个匹配的表格。 这些通常称为table1_2_table2,或者在您的情况下称为recipe2ingredient。 在其中存储两个表的主键(在大多数情况下,作为该表上的组合主键,这通常是有意义的)

菜单和菜谱也应如此,因为您可能想在多个菜单中使用一个菜谱。

所以

Table 1 - Menu    (ID, Name, ... whatever columns you need on top of that)
Table 2 - Recipe (ID, Name, ...whatever columns you could desire)
Table 3 - Menu2Recipe( IdMenu, IdRecipe)
Table 4 - Ingredient (ID, Name, measurement unit)
Table 5 - Ingredient2Recipe( IdRecipe, IdIngredient, Amount )

我希望这对你来说有点清楚。

【讨论】:

  • 好吧,我想我知道你的意思,而不是让我的主键在成分和配方中创建一个表,其中包含两者的主键,与配方和成分相同。我不完全理解这些关系是什么,这是否说明了一个食谱中的多种成分?很抱歉这些业余问题,但我已经为此绞尽脑汁了一段时间。
  • 这不是一个业余问题,你问它很好。无需将成分存储在一个表中的列中,您只需将它们输入到行中即可。也就是说你有Recipe AIngredient 1, 2, 3。如果配方 A 需要 1 和 3,您将在成分 2 配方表中有 2 行,其中 A,1A,3 作为列值(通过主键访问原始表的外键)。如果配方 B 需要所有 3 种现有成分,则该表将仅包含 B,1B,2B,3。这样你就不需要知道/限制最大值。成分的数量。
  • 好的,这有点帮助,所以我的配料表基本上会包含所有食谱所需的所有配料(我一直假设)假设我想查看含有配料 1、20 和 35 的食谱 D。这意味着成分 2 配方表将有 3 行,例如 D1、D20 和 D35。 D是餐名的ID,数字(1、20、35)是食材的ID?我认为这有助于我理解,但看不到最后,如果我想搜索含有 3 种成分的餐点,查询将如何工作? SELECT name, description FROM menu WHERE 这就是我迷路的地方
  • 您对 D1、D20 和 D35 的假设是正确的。从 SQL 的角度来看,搜索“具有”三种成分的膳食很容易,它是通过 GROUPING 完成的(参见 W3 中的教程 w3schools.com/sql/sql_groupby.asp 并遵循“具有”)。由于您应该/将把成分存储在另一个表中,这很可能通过分组连接来完成:SELECT r.name, COUNT(ir.*) FROM recipe r, ingredients2recipe ir WHERE ir.recipeId = r.id GROUP BY ir.recipeId HAVING COUNT(ir.*) = 3
  • 太棒了,感谢您的帮助,我去看看我能做到多远。它很可能会回来挑你的大脑来解决这个问题。再次感谢
【解决方案2】:

您的设计缺少一张桌子以提高效率;从您的配方表中删除 iName1 到 iName3 并添加一个映射表“recipe_ingredients”,其中包含配方和一种成分的外键。然后,对于每个食谱,您将在该表中拥有一到多行(看我的示例)。但是:您可以轻松搜索使用某种成分的所有食谱。如果需要,您可以在一份食谱中使用 10000 种成分。

餐桌菜单与食谱有何关联?菜单是否总是包含一个食谱?否则,还要为该关系添加一个映射表。

SELECT mName, mDiscription, mAllergy 
    FROM menu
        JOIN recipe ON recipe.mName = menu.mName
        JOIN recipe_ingredients ON recipe_ingredients.mName = recipe.mName
    WHERE recipe_ingredients.iName = 'whatever'

【讨论】:

  • 我希望菜单中的每一行对应于食谱中的一行,即菜单中的每餐都有自己的食谱。因为我更像是一个网络“设计师”而不是“开发人员”,而且在编写 php(mySQL)、javascript 和我对表之间的关系(应该)如何进行编码时效率不高工作:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-04
  • 1970-01-01
  • 2014-07-09
  • 2011-04-14
  • 1970-01-01
  • 2020-05-13
相关资源
最近更新 更多