将一个表通过其他表连接到另一个表

时间:2016-04-12 12:03:11

标签: mysql sql database

我正在努力在搜索查询中表达我想要做的事情,所以如果以前已经回答过,我很抱歉。我希望通过发布一个完整的例子,某人能够指出我正确的方向。我希望找出一个mySQL查询,或者学习一种更好的方法来构建我的数据库,以实现以下目标。

如果我有4个表,那么将表格链接到另一个表格的最佳方法是什么。下面我有一个site_table,其中包含经理(网站总经理),地区和国家/地区的ID。 region_table和country_table也指向manager_table。 site_table上的manager_id也指向manager_table。以下是表格的外观:

site_table
+------------+------------+-----------+------------+
|    name    | manager_id | region_id | country_id |
+------------+------------+-----------+------------+
| Manchester |          1 |         1 |          1 |
| Essex      |          2 |         2 |          1 |
| Perth      |          3 |         3 |          2 |
| Birmingham |          4 |         1 |          1 |
+------------+------------+-----------+------------+

region_table
+-----------+---------+------------+
| region_id |  name   | manager_id |
+-----------+---------+------------+
|         1 | Central |          5 |
|         2 | South   |          6 |
|         3 | North   |          7 |
+-----------+---------+------------+

country_table
+------------+----------+------------+
| country_id |   name   | manager_id |
+------------+----------+------------+
|          1 | England  |          9 |
|          2 | Scotland |          8 |
+------------+----------+------------+

manager_table
+------------+-----------------+
| manager_id |      name       |
+------------+-----------------+
|          1 | Joe Bloggs      |
|          2 | Graham Smith    |
|          3 | Pat Sharp       |
|          4 | Sally May       |
|          5 | Peter Barratt   |
|          6 | Jimmy Stone     |
|          7 | Kim Keller      |
|          8 | Peter Sheet     |
|          9 | Matthew Lampart |
+------------+-----------------+

我想查询数据库以返回网站名称,总经理(GM)名称,区域经理(RM)名称和国家/地区经理(CM)名称,如此:

+------------+--------------+---------------+-----------------+
| site_name  |   GM_name    |    RM_name    |     CM_name     |
+------------+--------------+---------------+-----------------+
| Manchester | Joe Bloggs   | Peter Barratt | Matthew Lampart |
| Essex      | Graham Smith | Jimmy Stone   | Matthew Lampart |
| Perth      | Pat Sharp    | Kim Keller    | Peter Sheet     |
| Birmingham | Sally May    | Peter Barratt | Matthew Lampart |
+------------+--------------+---------------+-----------------+

我想这样做我必须将site_table链接到region_table和country_table,然后将manager_table链接到site_table,region_table和country_table,但我试图将自己绑在一起。我看到链接看起来像这样:

site_table---+-----------------------+
             |                       |
             +-----region_table----manager_table
             |                       |
             +----country_table------+

如果有人可以就编写此查询的最佳方式提供任何建议,或者更好的方法来构建数据库,那将非常有用。

2 个答案:

答案 0 :(得分:3)

所以直截了当的答案是:

select
  s.name site_name,
  gm.name GM_name,
  rm.name RM_name,
  cm.name CM_name
from
  site_table s
  inner join manager_table gm on gm.manager_id = s.manager_id
  inner join region_table r on r.region_id = s.region_id
  inner join manager_table rm on rm.manager_id = r.manager_id
  inner join country_table c on c.country_id = s.country_id
  inner join manager_table cm on cm.manager_id = c.manager_id;

但这真的只有在每个GM,RM和CM总是至少有一个区域和经理时才有效。更灵活的东西可能是:

select
  s.name site_name,
  gm.name GM_name,
  rm.name RM_name,
  cm.name CM_name
from
  site_table s
  left outer join manager_table gm on gm.manager_id = s.manager_id
  left outer join region_table r on r.region_id = s.region_id
  left outer join manager_table rm on rm.manager_id = r.manager_id
  left outer join country_table c on c.country_id = s.country_id
  left outer join manager_table cm on cm.manager_id = c.manager_id;

这将处理您可能缺少经理或地区的情况,但效率会低一些。

希望这些帮助!

答案 1 :(得分:2)

尝试使用CASE EXPRESSION使用条件聚合。你的想法是正确的,你需要首先加入所有三个表,然后你可以看到我加入了m.manager_id IN(s.manager_id,r.manager_id,c.manager_id)上的经理表。之后的聚合是为了转动输出,因为每个名称将有3条记录,每个表都包含manager_name。

SELECT s.name,
      MAX(CASE WHEN s.manager_id = m.manager_id THEN m.name END) as GM_NAME,
      MAX(CASE WHEN r.manager_id= m.manager_id THEN m.name END) as RM_NAME,
      MAX(CASE WHEN c.manager_id = m.manager_id THEN m.name END) as CM_NAME
FROM site_table s
INNER JOIN region_table r ON(s.region_id = r.region_id)
INNER JOIN country_table c ON(s.country_id = c.country_id)
INNER JOIN manager_table m ON(m.manager_id IN(s.manager_id,r.manager_id,c.manager_id))
GROUP BY s.name

如果你可能有丢失的数据 - 在任何site_table id列上都是空的,这对你提供的数据听起来不太合理,甚至是这个结构的想法,那么使用左连接

SELECT s.name,
      MAX(CASE WHEN s.manager_id = m.manager_id THEN m.name END) as GM_NAME,
      MAX(CASE WHEN r.manager_id= m.manager_id THEN m.name END) as RM_NAME,
      MAX(CASE WHEN c.manager_id = m.manager_id THEN m.name END) as CM_NAME
FROM site_table s
LEFT JOIN region_table r ON(s.region_id = r.region_id)
LEFT JOIN country_table c ON(s.country_id = c.country_id)
LEFT JOIN manager_table m ON(m.manager_id IN(s.manager_id,r.manager_id,c.manager_id))
GROUP BY s.name