我的MySql查询是否有更短的替代方案?

时间:2018-04-05 14:58:54

标签: mysql many-to-many union outer-join linktable

我是Java的学生,也做SQL。在课程中,我们看到了一个示例数据库草图,以及在此问题中复制的查询。

我用MySql做了一个例子,它有三个表,

CREATE TABLE `employed` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

CREATE TABLE `department` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

CREATE TABLE `employees_departments` (
`employed_id` int(11) NOT NULL,
`department_id` int(11) NOT NULL,
PRIMARY KEY (`employed_id`,`department_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

受雇于

(1 'Karl'), (2 'Bengt'), (3 'Adam'), (4 'Stefan')

部门充满了

(4, 'HR'), (5, 'Sälj'), (6, 'New departm')

employees_departments充满了

1 4
2 5
3 4

所以" Stefan"没有部门,"新部门"没有工作。

我想要一个可以为员工提供所有部门的查询,以及没有部门和部门但没有员工的员工。我找到了这样的解决方案:

select A.name, C.name from employed A
left join employees_departments B on (A.id=B.employed_id)
left join department C on (B.department_id = C.id)
union
select C.name, A.name from department A
left join employees_departments B on (A.id=B.department_id)
left join employed C on (B.employed_id = C.id)

如果有一个简短的查询来制作它会很好......

另外,我在没有外键约束的情况下做了这个,因为我希望这个例子尽可能简单。

问候

1 个答案:

答案 0 :(得分:1)

MySQL不支持FULL OUTER加入操作。

我们可以通过组合两个集合来模拟它......一个OUTER JOIN的结果和一个反JOIN的结果。

(
  SELECT ee.name        AS employed_name
       , dd.name        AS department_name 
    FROM employed ee
    LEFT
    JOIN employees_departments ed
      ON ed.employed_id = ee.id
    LEFT
    JOIN department dd
      ON dd.id = ed.department_id
)
UNION ALL 
(
  SELECT nn.name        AS employed_name
       , nd.name        AS department_name
    FROM department nd
    LEFT
    JOIN employees_departments ne
      ON ne.deparment_id = nd.id
    LEFT
    JOIN employeed nn
      ON nn.id = nd.employee_id
   WHERE nn.id IS NULL
)

第一个SELECT返回所有employed名称以及匹配的department名称,包括没有employed的{​​{1}}。

第二个SELECT仅返回department中没有匹配行的department名称。

使用employed集合运算符组合/连接两个SELECT的结果。 (UNION ALL操作避免了使用UNION ALL集合运算符强制执行的使用filesort"操作的潜在代价。

这是返回这些行的最短查询模式。

我们可以让SQL更短一些。例如,如果我们在UNIONemployeed_department之间存在外键关系(原始帖子中没有指出强制执行此类关系,那么我们不假设有一个关系)。 ..但如果强制执行,那么我们可以省略第二个SELECT

中的employed
employed

有了合适的索引,这将为我们提供最有效的访问计划。

是否有更短的SQL会返回相同的结果?如果有,它可能不会像上面那样有效。