我的 MySql 查询是否有更短的替代方案?
Is there a shorter alternative to my MySql query?
我是 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 的结果和 anti-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 return 所有 employed
名称,以及匹配的 department
名称,包括没有 department
的 employed
.
第二个 SELECT return 只是 department
在 employed
中没有匹配行的名称。
两个 SELECT 的结果是 combined/concatenated 使用 UNION ALL
集合运算符。 (UNION ALL
操作避免了使用 UNION
集合运算符强制执行的潜在昂贵的 "Using filesort" 操作。
这是 return 这些行的最短查询模式。
我们可以让 SQL 短一点。例如,如果我们在 employeed_department
和 employed
之间有一个外键关系(在原始 post 中没有指示这种关系是强制执行的,所以我们不假设有一个)...但是如果强制执行,那么我们可以省略第二个 SELECT
中的 employed
table
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
)
有了可用的 suitable 索引,这将为我们提供最有效的访问计划。
是否有更短的 SQL 可以 return 得到相同的结果?如果有,它可能不会像上面那样有效地执行。
我是 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 的结果和 anti-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 return 所有 employed
名称,以及匹配的 department
名称,包括没有 department
的 employed
.
第二个 SELECT return 只是 department
在 employed
中没有匹配行的名称。
两个 SELECT 的结果是 combined/concatenated 使用 UNION ALL
集合运算符。 (UNION ALL
操作避免了使用 UNION
集合运算符强制执行的潜在昂贵的 "Using filesort" 操作。
这是 return 这些行的最短查询模式。
我们可以让 SQL 短一点。例如,如果我们在 employeed_department
和 employed
之间有一个外键关系(在原始 post 中没有指示这种关系是强制执行的,所以我们不假设有一个)...但是如果强制执行,那么我们可以省略第二个 SELECT
employed
table
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
)
有了可用的 suitable 索引,这将为我们提供最有效的访问计划。
是否有更短的 SQL 可以 return 得到相同的结果?如果有,它可能不会像上面那样有效地执行。