是否有可能一次加入多对多和一对多?

时间:2017-09-26 19:51:11

标签: mysql join

我的表格有以下架构: wp_careers enter image description here

wp_locations enter image description here

wp_careers_locations enter image description here

wp_educations enter image description here

职业申请人可以申请许多地方,并有很多教育记录。

所需的结果是从wp_careers获取所有记录并将应用的位置分组为位置字段,并将所有教育记录(wp_educations)作为附加到申请人的数组。

现在我知道如何加入多对多的关系并将这些地点分组:

  SELECT c.*, GROUP_CONCAT(l.name) as locations
  FROM wp_careers c
  JOIN wp_careers_locations cl ON c.id = cl.career_id
  JOIN wp_locations l ON cl.location_id = l.id
  GROUP BY c.id

但我不知道如何扩展此查询以包含教育记录。

1 个答案:

答案 0 :(得分:1)

一种方法是再次加入:

SELECT c.*, GROUP_CONCAT(DISTINCT l.name) as locations,
  GROUP_CONCAT(DISTINCT e.institute) AS edu_institutes
FROM wp_careers c
LEFT JOIN wp_careers_locations cl ON c.id = cl.career_id
LEFT JOIN wp_locations l ON cl.location_id = l.id
LEFT JOIN wp_educations e ON c.id = e.career_id
GROUP BY c.id

但这很可能会产生一个Cartesian product,因为它会无意中加入每个教育的每个地方。因此,如果您有针对特定职业的三个地点和两个教育,那么当您没有预期时,它将生成3x2 = 6行。我尝试使用DISTINCT来补偿这一点,因此每个GROUP_CONCAT()中的名称列表将消除重复。

但老实说,我更愿意运行两个查询。一个用于位置,另一个用于教育。这样可以避免笛卡尔积。 MySQL不是那么脆弱,它无法处理额外的查询,它实际上可能比执行DISTINCT操作更便宜。

重新评论:

您是想将教育查询中的职业只限于那些至少有一个职位的职业吗?

您可以使用半连接执行此操作:

SELECT c.*, GROUP_CONCAT(e.institute) AS edu_institutes
FROM wp_careers c
JOIN wp_educations e ON c.id = e.career_id
WHERE c.id IN (SELECT career_id FROM wp_career_locations)
GROUP BY c.id

即使wp_career_locations中可能有多行匹配每个相应的c.id,但它不会导致笛卡尔积。