SQL 多列内部联接

SQL Inner Join With Multiple Columns

我有 2 个表 - 菜肴配料:

Dishes 中, 我有一份披萨菜肴清单,顺序如下:

成分中,我列出了所有菜肴的所有不同成分,顺序如下:

我希望能够在每道菜的名称旁边列出每道菜所有成分的所有名称

我写的这个查询没有用名称替换成分 ID,而是选择 return 一个空集 - 请解释我做错了什么:

    SELECT dishes.name, ingredients.name, ingredients.id
FROM dishes
INNER JOIN ingredients
ON dishes.ingredient_1=ingredients.id,dishes.ingredient_2=ingredients.id,dishes.ingredient_3=ingredients.id,dishes.ingredient_4=ingredients.id,dishes.ingredient_5=ingredients.id,dishes.ingredient_6=ingredients.id, dishes.ingredient_7=ingredients.id,dishes.ingredient_8=ingredients.id;

如果能参考一下就好了:

  1. 数据库结构的逻辑 - 我做的对吗?
  2. SQL 查询背后的逻辑 - 如果数据库以正确的方式构建,那么为什么在执行查询时我得到空集?
  3. 如果您以前遇到过这样的问题 - 需要单对多关系 - 您是如何以不同于此的方式解决它的,使用 PHP & MySQL?

无视希伯来文文本 - 将其视为您自己的语言。

在我看来,更好的数据库结构应该有一个 Dishes_Ingredients_Rel table,而不是一堆成分列。

DISHES_INGREDIENTS_REL
DishesID
IngredientID

然后,您可以做一个更简单的 JOIN。

SELECT Ingredients.Name
FROM Dishes_Ingredients_Rel
    INNER JOIN Ingredients
        ON Dishes_Ingredients.IngredientID = Ingredients.IngredientID
WHERE Dishes_Ingredients_Rel.DishesID = @DishesID

1.数据库结构的逻辑 - 我做得对吗?

  • 这是非规范化数据。要对其进行规范化,您需要将数据库重组为三个 table:
    • Pizza
    • PizzaIngredients
    • Ingredients

Pizza 将有 IDnametype,其中 ID 是主键。

PizzaIngredients 会有 PizzaIdIngredientId(这是一个多对多 table,其中主键是 PizzaIdIngredientID)

IngredientsIDname,其中 ID 是主键。

2。在每道菜的名称旁边列出每道菜所有成分的所有名称。 MySQL 中的类似内容(未经测试):

SELECT p.ID, p.name, GROUP_CONCAT(i.name) AS ingredients
FROM pizza p
INNER JOIN pizzaingredients pi ON p.ID = pi.PizzaID
INNER JOIN ingredients i ON pi.IngredientID = i.ID
GROUP BY p.id

3。如果您以前遇到过这样的问题 - 一个需要单对多关系的问题 - 您是如何以不同于此的方式解决它的,使用 PHP & MySQL?

  • 使用多对多关系,因为这就是您的示例的真实情况。你有很多披萨,里面有很多配料。许多成分属于许多不同的比萨饼。

您得到空结果的原因是您设置了一个永远不会满足的连接条件。在 INNER join 执行期间,数据库引擎将第一个 table 的每条记录与第二个记录的每条记录进行比较,试图找到一个匹配项,其中被评估的成分 table 记录的 ID 等于成分 1 AND成分 2 等等。如果您在第一个 table 中创建一条记录,在所有 8 列中使用相同的成分(仅用于测试目的),它会 return 一些结果。

关于数据库结构,您选择非规范化的结构,为每种成分创建 8 列。这个数据结构有很多可能的考虑因素(性能、可维护性,或者只是想如果你被要求插入一个包含 9 种成分的菜),我个人会选择一个规范化的数据结构。

但是如果你想保留这个,你应该这样写:

SELECT dishes.name, ingredients1.name, ingredients1.id, ingredients2.name, ingredients2.id, ...
FROM dishes
LEFT JOIN ingredients AS ingredients1 ON dishes.ingredient_1=ingredients1.id
LEFT JOIN ingredients AS ingredients2 ON dishes.ingredient_2=ingredients2.id
LEFT JOIN ingredients AS ingredients3 ON dishes.ingredient_3=ingredients3.id
...

需要 LEFT 连接才能获得不匹配成分的结果(阅读您的示例时未设置任何成分时值为 0)