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;
如果能参考一下就好了:
- 数据库结构的逻辑 - 我做的对吗?
- SQL 查询背后的逻辑 - 如果数据库以正确的方式构建,那么为什么在执行查询时我得到空集?
- 如果您以前遇到过这样的问题 - 需要单对多关系 - 您是如何以不同于此的方式解决它的,使用 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
将有 ID
、name
和 type
,其中 ID
是主键。
PizzaIngredients
会有 PizzaId
和 IngredientId
(这是一个多对多 table,其中主键是 PizzaId
和IngredientID
)
Ingredients
有 ID
和 name
,其中 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)
我有 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;
如果能参考一下就好了:
- 数据库结构的逻辑 - 我做的对吗?
- SQL 查询背后的逻辑 - 如果数据库以正确的方式构建,那么为什么在执行查询时我得到空集?
- 如果您以前遇到过这样的问题 - 需要单对多关系 - 您是如何以不同于此的方式解决它的,使用 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
将有 ID
、name
和 type
,其中 ID
是主键。
PizzaIngredients
会有 PizzaId
和 IngredientId
(这是一个多对多 table,其中主键是 PizzaId
和IngredientID
)
Ingredients
有 ID
和 name
,其中 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)