如何检查一对多映射中是否存在特定映射 table
How to check if a particular mapping exists in a one-to-many mapping table
我有一个 table 维护 EMPLOYEE_ID
到可以分配给员工的一个或多个 ROLE_ID
的映射。 ROLE_ID
是 ROLE
table 的主键。
现在,我正在尝试查找某个员工是否是团队负责人 (ROLE_ID = 2)。也就是说,从本质上讲,试图找出 (EMPLOYEE_ID, 2) 的特定映射组合是否存在于映射 table.
中
目前,我正在使用以下查询来实现此目的:
SELECT E.NAME AS `EMPLOYEE_NAME`,
EXISTS( SELECT 1 FROM `EMPLOYEE_ROLE` WHERE
(`EMPLOYEE_ROLE`.`EMPLOYEE_ID` = `E`.`EMPLOYEE_ID`)
AND (`EMPLOYEE_ROLE`.`ROLE_ID` = 2)) AS `IS_TEAM_LEADER`
-- Assume some other column shall be selected from ER table,
-- hence necessitating the JOIN on ER
FROM EMPLOYEE E
JOIN EMPLOYEE_ROLE ER ON (ER.EMPLOYEE_ID = E.EMPLOYEE_ID)
GROUP BY E.EMPLOYEE_ID;
虽然这似乎可以完成工作,但我正在寻找一种更有效的方法,因为当前形式的子查询似乎是多余的。不确定它是否相关,但是可以使用 FIND_IN_SET
或类似的函数吗?
任何人都可以提出解决方案,因为我对性能最佳的方法感兴趣吗?
编辑 1:我有意使用 JOIN EMPLOYEE_ROLE
,目的是也可以从 ER
table 中选取其他列。所以,我正在寻找优化子查询,同时保持连接不变。因此,语句 "current subquery in its current form seems redundant".
SQLFiddle:http://sqlfiddle.com/#!9/2aad3/5
使用 exists 子查询或使用 join,但不应在一个查询中同时使用两者。
我会使用连接方法,因为在必要时很容易获得与角色相关的数据:
SELECT E.NAME AS `EMPLOYEE_NAME`,
FROM EMPLOYEE E
INNER JOIN EMPLOYEE_ROLE ER ON (ER.EMPLOYEE_ID = E.EMPLOYEE_ID)
WHERE ER.ROLE_ID=2;
如果您需要一个包含所有员工的列表,其中有一个字段指示该员工是否是 IS 领导者,请使用左连接而不是内部连接:
SELECT DISTINCT E.NAME AS `EMPLOYEE_NAME`, IF(ER.ROLE_ID IS NULL, 'NOT IS Leader','IS Leader') AS IsISLeader
FROM EMPLOYEE E
LEFT JOIN EMPLOYEE_ROLE ER ON ER.EMPLOYEE_ID = E.EMPLOYEE_ID AND ER.ROLE_ID=2;
"best performing" --
CREATE TABLE `EMPLOYEE_ROLE` (
`EMPLOYEE_ID` INT NOT NULL,
`ROLE_ID` INT NOT NULL,
PRIMARY KEY(`EMPLOYEE_ID`, ROLE_ID),
INDEX(`ROLE_ID` EMPLOYEE_ID)
) ENGINE=InnoDB;
Why.
除此之外,请参阅@Shadow 的回答。
我在 SQL 中包含 EMPLOYEE_ID 以防发现不同 EMPLOYEE_ID 的相同名称,如果某些员工没有角色,也使用 LEFT JOIN:
SELECT E.EMPLOYEE_ID, E.NAME, SUM(IF(R.ROLE_ID=2,1,0)) IS_TEAM_LEADER
FROM EMPLOYEE E
LEFT JOIN EMPLOYEE_ROLE R ON E.EMPLOYEE_ID = R.EMPLOYEE_ID
GROUP BY 1,2
简单使用FK关系
创建角色 Table 为
table role{
RoleID
RoleName
Status
...}
并将员工 table 编辑为
table employee{
ID
name
...
}
创建table 员工角色
table employeerole{
ID
roleID
employeeID
}
现在您也可以使用规范化规则为每个员工管理多个角色
现在您可以使用查询
SELECT employee.ID, employee.Name, employeerole.roleid FROM role
INNER JOIN employeerole ON role.RoleID = employeerole.roleid INNER
JOIN dbo.employee ON dbo.employeerole.employeeid = dbo.employee.ID
WHERE employeerole.roleid = 2
table 角色的 ID 为 2,名称例如是组长或经理
现在此查询已完全优化,将为您提供最佳结果
如果我没理解错的话,您是在尝试获取所有员工及其所有角色,以及一个额外的列来表明他们是否是团队领导。如果是这样,您只需要加入 EMPLOYEE_ROLE
两次,第二次是 LEFT JOIN
只是为了检查特定角色:
SELECT E.NAME, ER.ROLE_ID, ER2.EMPLOYEE_ID IS NOT NULL AS `IS_TEAM_LEADER`
FROM EMPLOYEE E
JOIN EMPLOYEE_ROLE ER ON ER.EMPLOYEE_ID = E.EMPLOYEE_ID
LEFT JOIN EMPLOYEE_ROLE ER2 ON ER2.EMPLOYEE_ID = E.EMPLOYEE_ID AND ER2.ROLE_ID = 2;
SQL Fiddle: http://sqlfiddle.com/#!9/2aad3/9/0
这是获取属于特定角色的所有员工的查询
SELECT e.NAME FROM EMPLOYEE e right join (SELECT EMPLOYEE_ID FROM
EMPLOYEE_ROLE WHERE ROLE_ID=2) er using(EMPLOYEE_ID);
我有一个 table 维护 EMPLOYEE_ID
到可以分配给员工的一个或多个 ROLE_ID
的映射。 ROLE_ID
是 ROLE
table 的主键。
现在,我正在尝试查找某个员工是否是团队负责人 (ROLE_ID = 2)。也就是说,从本质上讲,试图找出 (EMPLOYEE_ID, 2) 的特定映射组合是否存在于映射 table.
中目前,我正在使用以下查询来实现此目的:
SELECT E.NAME AS `EMPLOYEE_NAME`,
EXISTS( SELECT 1 FROM `EMPLOYEE_ROLE` WHERE
(`EMPLOYEE_ROLE`.`EMPLOYEE_ID` = `E`.`EMPLOYEE_ID`)
AND (`EMPLOYEE_ROLE`.`ROLE_ID` = 2)) AS `IS_TEAM_LEADER`
-- Assume some other column shall be selected from ER table,
-- hence necessitating the JOIN on ER
FROM EMPLOYEE E
JOIN EMPLOYEE_ROLE ER ON (ER.EMPLOYEE_ID = E.EMPLOYEE_ID)
GROUP BY E.EMPLOYEE_ID;
虽然这似乎可以完成工作,但我正在寻找一种更有效的方法,因为当前形式的子查询似乎是多余的。不确定它是否相关,但是可以使用 FIND_IN_SET
或类似的函数吗?
任何人都可以提出解决方案,因为我对性能最佳的方法感兴趣吗?
编辑 1:我有意使用 JOIN EMPLOYEE_ROLE
,目的是也可以从 ER
table 中选取其他列。所以,我正在寻找优化子查询,同时保持连接不变。因此,语句 "current subquery in its current form seems redundant".
SQLFiddle:http://sqlfiddle.com/#!9/2aad3/5
使用 exists 子查询或使用 join,但不应在一个查询中同时使用两者。
我会使用连接方法,因为在必要时很容易获得与角色相关的数据:
SELECT E.NAME AS `EMPLOYEE_NAME`,
FROM EMPLOYEE E
INNER JOIN EMPLOYEE_ROLE ER ON (ER.EMPLOYEE_ID = E.EMPLOYEE_ID)
WHERE ER.ROLE_ID=2;
如果您需要一个包含所有员工的列表,其中有一个字段指示该员工是否是 IS 领导者,请使用左连接而不是内部连接:
SELECT DISTINCT E.NAME AS `EMPLOYEE_NAME`, IF(ER.ROLE_ID IS NULL, 'NOT IS Leader','IS Leader') AS IsISLeader
FROM EMPLOYEE E
LEFT JOIN EMPLOYEE_ROLE ER ON ER.EMPLOYEE_ID = E.EMPLOYEE_ID AND ER.ROLE_ID=2;
"best performing" --
CREATE TABLE `EMPLOYEE_ROLE` (
`EMPLOYEE_ID` INT NOT NULL,
`ROLE_ID` INT NOT NULL,
PRIMARY KEY(`EMPLOYEE_ID`, ROLE_ID),
INDEX(`ROLE_ID` EMPLOYEE_ID)
) ENGINE=InnoDB;
Why.
除此之外,请参阅@Shadow 的回答。
我在 SQL 中包含 EMPLOYEE_ID 以防发现不同 EMPLOYEE_ID 的相同名称,如果某些员工没有角色,也使用 LEFT JOIN:
SELECT E.EMPLOYEE_ID, E.NAME, SUM(IF(R.ROLE_ID=2,1,0)) IS_TEAM_LEADER
FROM EMPLOYEE E
LEFT JOIN EMPLOYEE_ROLE R ON E.EMPLOYEE_ID = R.EMPLOYEE_ID
GROUP BY 1,2
简单使用FK关系 创建角色 Table 为
table role{
RoleID
RoleName
Status
...}
并将员工 table 编辑为
table employee{
ID
name
...
}
创建table 员工角色
table employeerole{
ID
roleID
employeeID
}
现在您也可以使用规范化规则为每个员工管理多个角色
现在您可以使用查询
SELECT employee.ID, employee.Name, employeerole.roleid FROM role
INNER JOIN employeerole ON role.RoleID = employeerole.roleid INNER
JOIN dbo.employee ON dbo.employeerole.employeeid = dbo.employee.ID
WHERE employeerole.roleid = 2
table 角色的 ID 为 2,名称例如是组长或经理
现在此查询已完全优化,将为您提供最佳结果
如果我没理解错的话,您是在尝试获取所有员工及其所有角色,以及一个额外的列来表明他们是否是团队领导。如果是这样,您只需要加入 EMPLOYEE_ROLE
两次,第二次是 LEFT JOIN
只是为了检查特定角色:
SELECT E.NAME, ER.ROLE_ID, ER2.EMPLOYEE_ID IS NOT NULL AS `IS_TEAM_LEADER`
FROM EMPLOYEE E
JOIN EMPLOYEE_ROLE ER ON ER.EMPLOYEE_ID = E.EMPLOYEE_ID
LEFT JOIN EMPLOYEE_ROLE ER2 ON ER2.EMPLOYEE_ID = E.EMPLOYEE_ID AND ER2.ROLE_ID = 2;
SQL Fiddle: http://sqlfiddle.com/#!9/2aad3/9/0
这是获取属于特定角色的所有员工的查询
SELECT e.NAME FROM EMPLOYEE e right join (SELECT EMPLOYEE_ID FROM
EMPLOYEE_ROLE WHERE ROLE_ID=2) er using(EMPLOYEE_ID);