简体   繁体   English

SQL内部联接多列

[英]SQL Inner Join With Multiple Columns

I've got 2 tables - dishes and ingredients : 我有2张桌子- 菜肴配料

in Dishes, I've got a list of pizza dishes, ordered as such: 菜肴中,我有一份比萨饼清单,按以下顺序订购: 菜桌

In Ingredients, I've got a list of all the different ingredients for all the dishes, ordered as such: 在“ 配料”中,我列出了所有菜肴的所有不同配料,并按以下顺序排列: 成分表

I want to be able to list all the names of all the ingredients of each dish alongside each dish's name . 我希望能够在每个菜名旁边列出每个菜的所有成分的所有名称

I've written this query that does not replace the ingredient ids with names as it should, instead opting to return an empty set - please explain what it that I'm doing wrong: 我写了这个查询,没有用名称替换成分ID,而是选择返回一个空集-请说明我做错了什么:

    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;

It would be great if you could refer to: 如果您可以参考:

  1. The logic of the DB structuring - am I doing it correctly? 数据库结构的逻辑 -我做对了吗?
  2. The logic behind the SQL query - if the DB is built in the right fashion, then why upon executing the query I get the empty set? SQL查询背后的逻辑 -如果以正确的方式构建数据库,那么为什么在执行查询时得到空集?
  3. If you've encountered such a problem before - one that requires a single-to-many relationship - how did you solved it in a way different than this, using PHP & MySQL? 如果您之前曾遇到过这样的问题-一个需要一对多关系的问题 -您是如何使用PHP和MySQL以不同于此的方式解决此问题的?

Disregard The Text In Hebrew - Treat It As Your Own Language. 忽略希伯来语中的文本-将其视为您自己的语言。

It seems to me that a better Database Structure would have a Dishes_Ingredients_Rel table, rather than having a bunch of columns for Ingredients. 在我看来,更好的数据库结构将具有Dishes_Ingredients_Rel表,而不是具有一堆用于成分的列。

DISHES_INGREDIENTS_REL
DishesID
IngredientID

Then, you could just do a much simpler JOIN. 然后,您可以做一个简单得多的JOIN。

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

1. The logic of the DB structuring - am I doing it correctly? 1.数据库结构的逻辑-我做对了吗?

  • This is denormalized data. 这是非规范化数据。 To normalize it, you would restructure your database into three tables: 为了对其进行规范化,需要将数据库重组为三个表:
    • Pizza
    • PizzaIngredients
    • Ingredients

Pizza would have ID , name , and type where ID is the primary key. Pizza将具有IDnametype ,其中ID是主键。

PizzaIngredients would have PizzaId and IngredientId (this is a many-many table where the primary key is a composite key of PizzaId and IngredientID ) PizzaIngredients将具有PizzaIdIngredientId (这是一个很多表,其中主键是PizzaIdIngredientID的复合键)

Ingredients has ID and name where ID is the primary key. Ingredients具有IDname ,其中ID是主键。

2. List all the names of all the ingredients of each dish alongside each dish's name. 2.在每个菜名旁边列出每个菜所有成分的所有名称。 Something like this in MySQL (untested): 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. If you've encountered such a problem before - one that requires a single-to-many relationship - how did you solved it in a way different than this, using PHP & MySQL? 3.如果以前遇到过这样的问题-需要单对多关系-您是如何使用PHP和MySQL以不同于此的方式解决此问题的?

  • Using a many-many relationship, since that what your example truly is. 使用多对多关系,因为这就是您的例子的真实含义。 You have many pizzas which can have many ingredients. 您有很多比萨饼,其中可以包含许多成分。 And many ingredients belong to many different pizzas. 许多食材属于许多不同的披萨。

The reason you are getting an empty result is because you are setting a join condition that never gets satisfied. 得到空结果的原因是因为您设置的连接条件永远不会满足。 During the INNER join execution the database engine compares each record of the first table with each record of the second one trying to find a match where the id of the ingredient table record being evaluated is equal to ingredient1 AND ingredient2 AND so on. 在执行INNER联接期间,数据库引擎会将第一个表的每个记录与第二个表的每个记录进行比较,以尝试找到匹配项,其中要评估的成分表记录的ID等于Ingredient1 AND Ingredient2等等。 It would return some result if you create a record in the first table with the same ingredient in all 8 columns (testing purposes only). 如果您在第一个表中创建的记录在所有8列中都具有相同的成分,则将返回一些结果(仅用于测试目的)。

Regarding the database structure, you choose a denormalized one creating 8 columns for each ingredient. 关于数据库结构,您选择一个非规范化的数据库,为每种成分创建8列。 There are a lot of considerations possible on this data structure (performance, maintainability, or just think if you are asked to insert a dish with 9 ingredients for example) and I would personally go for a normalized data structure instead. 在此数据结构上有很多考虑因素(性能,可维护性,或者仅考虑是否要求您插入包含9种成分的菜肴),我个人将使用标准化数据结构。

But if you want to keep this, you should write something like: 但是,如果要保留此内容,则应编写如下内容:

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
...

The LEFT join is required to get a result for unmatched ingredients (0 value when no ingredient is set reading your example) 需要LEFT联接才能获得不匹配成分的结果(在您的示例中未设置任何成分时为0值)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM