如何检查一对多映射表中是否存在特定映射

时间:2015-12-14 10:20:27

标签: mysql query-performance

我有一个表,用于维护EMPLOYEE_ID到可以分配员工的一个或多个ROLE_ID的映射。 ROLE_IDROLE表的主键。

现在,我正在尝试查找特定员工是否是团队负责人(ROLE_ID = 2)。也就是说,本质上,试图找出映射表中是否存在(EMPLOYEE_ID,2)的特定映射组合。

目前,我使用以下查询来实现此目的:

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表中挑选其他一些列。所以,我正在寻找优化子查询,同时保持连接完好无损。因此,当前形式的声明"当前子查询似乎是多余的"。

SQLFiddle:http://sqlfiddle.com/#!9/2aad3/5

6 个答案:

答案 0 :(得分:6)

使用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领导者,那么请使用left join而不是inner:

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;

答案 1 :(得分:4)

"表现最佳" -

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的答案。

答案 2 :(得分:2)

我在SQL中包含EMPLOYEE_ID,以防其他EMPLOYEE_ID找到相同的NAME,如果某个员工没有角色,也可以使用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

答案 3 :(得分:2)

只需使用FK关系 创建一个角色表作为

table role{
RoleID
RoleName
Status
...}

并将员工表编辑为

table employee{
ID
name
...
}

创建table employeerole

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

表格角色具有ID 2,而名称例如是团队领导者或经理

现在此查询已完全优化,可为您提供最佳效果

答案 4 :(得分:0)

如果我理解正确,那么您正试图让所有员工担任所有角色,另外还有一个列表明他们是否是团队负责人。如果是这样,您只需要加入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小提琴:http://sqlfiddle.com/#!9/2aad3/9/0

答案 5 :(得分:0)

以下是获取属于特定角色的所有员工的查询

SELECT e.NAME FROM EMPLOYEE e right join (SELECT EMPLOYEE_ID FROM
EMPLOYEE_ROLE WHERE ROLE_ID=2) er using(EMPLOYEE_ID);