我有一个表,用于维护EMPLOYEE_ID
到可以分配员工的一个或多个ROLE_ID
的映射。 ROLE_ID
是ROLE
表的主键。
现在,我正在尝试查找特定员工是否是团队负责人(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
答案 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;
除此之外,请参阅@ 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;
答案 5 :(得分:0)
以下是获取属于特定角色的所有员工的查询
SELECT e.NAME FROM EMPLOYEE e right join (SELECT EMPLOYEE_ID FROM
EMPLOYEE_ROLE WHERE ROLE_ID=2) er using(EMPLOYEE_ID);