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

标签 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”没有部门,“New departm”也没有雇员。

我想要一个查询,该查询将给出员工及其所有部门、没有部门的员工以及没有员工的部门。我发现这样的解决方案:

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)

如果能有一个简短的查询就更好了...

此外,我在没有外键约束的情况下进行了此操作,因为我希望在此示例中尽可能简单。

问候

最佳答案

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 名称,包括没有 departmentemployed >.

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

两个 SELECT 的结果使用 UNION ALL 集合运算符组合/串联。 (UNION ALL 操作避免了使用 UNION 集合运算符强制执行的潜在昂贵的“使用文件排序”操作。

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


我们可以让 SQL 更短一些。例如,如果我们在 employeed_departmentemployed 之间有一个外键关系(原始帖子中没有指示强制执行这种关系,所以我们不假设有是一个)......但是如果强制执行,那么我们可以从第二个 SELECT

中省略 employed
UNION ALL
(
  SELECT NULL           AS employed_name
       , nd.name        AS department_name
    FROM department nd
    LEFT
    JOIN employees_departments ne
      ON ne.deparment_id = nd.id
   WHERE ne.department_id IS NULL
)

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

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


关于mysql - 我的 MySql 查询是否有更短的替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49675534/

相关文章:

mysql - phpmyadmin权限表版本问题

mysql - 工作流程 - 如果所有记录均获得批准,则创建新行

php - 使用 PHP 创建和存储多个字段

Django - "ManyToMany"没有主键(AutoField)

mysql - 将 LIMIT 与 UNION 结合使用时 MariaDB 的奇怪行为

mongodb - MongoDB 中的 UNION 类似物

mysql - 独特的电影通过UNION两个连接的结果,MYSQL

mysql - 从用户未登录且不属于其他表行的一部分的表中选择用户

ios - iOS-核心数据关系。映射表/多对多关系

ruby-on-rails - 如何让 UsersPublisher 加入模型工作