MySQL中级表关系

时间:2015-05-27 20:58:28

标签: mysql

Table_1中的每一行都需要与一行或多行有关系,这些行可能来自数据库中的任意数量的其他表(Table_X)。所以我设置了一个中间表(Table_2),其中每一行包含Table_1中的id和Table_X中的id。它也有自己的自动增量ID,因为没有任何关系是独占的,因此其他ID在表中都不是唯一的。

我现在的问题是,当我从Table_1中检索行并希望查看Table_X中每个相关行的信息时,我不知道如何获取它。起初我以为我可以为Table_2中的每一行创建一个Table_X的确切名称列,并使用该信息创建第二个SELECT语句,但是我已经看到了关于外键和连接语句的内容。我想我需要进入。我只是在整理它时遇到了麻烦。我甚至需要Table_2吗?

这可能并不过分复杂,但我刚刚进入MySQL,这是我遇到的第一个真正的挑战。

编辑以包含所需信息:如果我理解正确,我认为我处理的是多对多的关系。 Table_3有游戏; Table_1有文章。一篇文章可以是关于多个游戏的,并且游戏也可以有多篇关于它的文章。我能看到的唯一其他可能相关的信息是,当一篇新文章被制作出来时,每一个与之相关的游戏都会立刻被决定。但随着更多文章的撰写,与特定游戏相关的文章列表会随着时间的推移而增长。然而,这可能并不是特别重要。

2 个答案:

答案 0 :(得分:2)

如果我理解正确您正在谈论数据库中的一对多关系(例如:一个人可以有多个电话号码),您可以将数据存储在两个单独的表personsphones中。

人:

|person_id|person_name  |person_age |
| 1       | Bodan Kustan| 28        |

电话:

|phone_id |person_id   |phone_number|
| 1       | 1          | 31337      |
| 2       | 1          | 370        |

然后您可以使用Join:

执行查询
SELLECT * FROM `persons`
  LEFT JOIN `phones` ON `persons`.`person_id` = `phones`.`person_id`
  WHERE `persons`.`person_id` = 1;

它将返回您的电话号码列表:

|person_id|person_name  |person_age |phone_id |person_id   |phone_number|
| 1       | Bodan Kustan| 28        | 1       | 1          | 31337      |
| 1       | Bodan Kustan| 28        | 2       | 1          | 370        |

另一种可能性是多对多的关系(例如:任何人都可以喜欢披萨,而披萨对于那个人来说并不是唯一的),那么你需要第三张桌子来加入桌子person_food

人:

|person_id|person_name  |person_age |
| 1       | Bodan Kustan| 28        |

食物:

|food_id |food_name |
| 1      | meat     |
| 2      | pizza    |

Person_Food

|person_id |food_id |
| 1        | 2      |

然后您可以使用Join:

执行查询
SELLECT * FROM `persons`
  LEFT JOIN `person_food` ON `person`.`person_id` = `person_food`.`person_id`
  LEFT JOIN `food` ON `food`.`food_id` = `person_food`.`food_id`
  WHERE `persons`.`person_id` = 1;

它将从所有表中返回数据:

|person_id|person_name  |person_age |person_id |food_id   |food_name |
| 1       | Bodan Kustan| 28        | 1        | 2        | pizza    |

但是,有时您需要加入n个表来加入,然后您可以使用单独的表来保存关于关系的信息。我的方法(我认为这不是最好的)是将表名存储在关系旁边(例如将手机和家庭电话分成两个独立的表):

人:

|person_id|person_name  |person_age |
| 1       | Bodan Kustan| 28        |

MOBILE_PHONE:

|mobile_phone_id |mobile_phone_number |
| 1              | 31337              |

HOME_PHONE:

|home_phone_id |home_phone_number |
| 1            | 370              |

Person_Phone:

|person_id |related_id |related_column   |related_table |
| 1        | 1         | mobile_phone_id | mobile_phone |
| 1        | 1         | home_phone_id   | home_phone   |

然后查询中间表以获得所有关系:

SELECT * FROM person_phone WHERE person_id = 1

然后构建动态查询(伪代码,未经测试 - 可能无效):

foreach (results as result)
  append_to_final_sql = "LEFT JOIN {related_table} 
    ON {related_table}.{related_column} = `person_phone`.`related_id`
    AND `person_phone`.`related_table` = {related_table}"
final_sql = "SELECT * FROM `persons` " 
  + append_to_final_sql + 
  " WHERE `persons`.`person_id` = 1"

所以你的最终SQL将是:

SELECT * FROM `persons`
  LEFT JOIN `person_phone` ON `person_phone`.`person_id` = `person`.`person_id`
  LEFT JOIN `mobile_phone` ON `mobile_phone`.`mobile_phone_id` = `person_phone`.`related_id` AND `person_phone`.`related_table` = 'mobile_phone'
  LEFT JOIN `home_phone` ON `home_phone`.`home_phone_id` = `person_phone`.`related_id` AND `person_phone`.`related_table` = 'home_phone'

答案 1 :(得分:0)

如果Table_x中的条目可以与Table1中的多行相关,则只需要Table2 - 否则Table1的简单键就足够了。

查看联接 - 非常强大,灵活和快速。

select * from Table1 left join Table2 on Table1_id = Table2_table_1_id
left join Table_X on Tablex_id = Table2_table_x_id

查看输出,您将看到它返回包含Table1和Table2字段副本的所有table_x行。