the answer by Alex works for me est une manière différente ici, sans ROW_NUMBER ...
Je pense que votre sortie de l'échantillon est erroné, pour cette solution:
SET NOCOUNT ON
DECLARE @T_Employee table (ID int, Name varchar(10))
INSERT @T_Employee VALUES(1, 'John')
INSERT @T_Employee VALUES(2, 'Jane')
INSERT @T_Employee VALUES(3, 'Joe')
DECLARE @T_Roles table (ID int, RoleName varchar(15))
INSERT @T_Roles VALUES(1, 'Clerk I')
INSERT @T_Roles VALUES(2, 'Clerk II')
INSERT @T_Roles VALUES(3, 'Manager')
INSERT @T_Roles VALUES(4, 'Senior Manager')
DECLARE @T_EmployeeRoles table (ID int, EmployeeID int, RoleID int)
INSERT @T_EmployeeRoles VALUES(1, 1, 1)
INSERT @T_EmployeeRoles VALUES(2, 1, 2)
INSERT @T_EmployeeRoles VALUES(3, 1, 3)
INSERT @T_EmployeeRoles VALUES(4, 2, 1)
INSERT @T_EmployeeRoles VALUES(5, 2, 2)
INSERT @T_EmployeeRoles VALUES(6, 2, 3)
INSERT @T_EmployeeRoles VALUES(7, 2, 4)
INSERT @T_EmployeeRoles VALUES(8, 3, 3)
INSERT @T_EmployeeRoles VALUES(9, 4, 4)
SET NOCOUNT OFF
;WITH CurrentInfo AS
(SELECT
e.ID AS EmployeeID, e.Name, r.RoleID AS CurrentRoleID, mr.ID AS EmployeeRoleID
FROM @T_Employee e
LEFT OUTER JOIN (SELECT
EmployeeID,MAX(ID) AS ID
FROM @T_EmployeeRoles
GROUP BY EmployeeID
) mr ON e.ID=mr.EmployeeID
LEFT OUTER JOIN @T_EmployeeRoles r ON mr.ID=r.ID
)
SELECT
c.EmployeeID AS ID, c.Name, r.RoleName AS "Current Role", llr.RoleName AS "Last Role"
FROM CurrentInfo c
LEFT OUTER JOIN @T_Roles r ON c.CurrentRoleID=r.ID
LEFT OUTER JOIN (SELECT
rr.EmployeeID,MAX(rr.ID) AS ID
FROM @T_EmployeeRoles rr
LEFT OUTER JOIN CurrentInfo cc ON rr.ID=cc.EmployeeRoleID
WHERE cc.EmployeeRoleID IS NULL
GROUP BY rr.EmployeeID
) mr ON c.EmployeeID=mr.EmployeeID
LEFT OUTER JOIN @T_EmployeeRoles lr ON mr.ID=lr.ID
LEFT OUTER JOIN @T_Roles llr ON lr.RoleID=llr.ID
SORTIE:
ID Name Current Role Last Role
----------- ---------- --------------- ---------------
1 John Manager Clerk II
2 Jane Senior Manager Manager
3 Joe Manager NULL
(3 row(s) affected)
Quand il n'y a qu'un « rôle actuel » parce que l'employé n'a travaillé que d'une position, vous pouvez appuyer sur le « rôle actuel » dans le « dernier rôle » en faisant cela dans le SELECT:
.. . , ISNULL(llr.RoleName,r.RoleName) AS "Last Role"
EDIT
ici est la version de la requête sans le CTE, il sera exécuté sur SQL Server 2000, j'ai aussi remplacé les tables variables avec des noms de table réelle du PO:
SELECT
c.EmployeeID AS ID, c.Name, r.RoleName AS "Current Role", llr.RoleName AS "Last Role"
FROM (SELECT
e.ID AS EmployeeID, e.Name, r.RoleID AS CurrentRoleID, mr.ID AS EmployeeRoleID
FROM T_Employee e
LEFT OUTER JOIN (SELECT
EmployeeID,MAX(ID) AS ID
FROM T_EmployeeRoles
GROUP BY EmployeeID
) mr ON e.ID=mr.EmployeeID
LEFT OUTER JOIN T_EmployeeRoles r ON mr.ID=r.ID
) c
LEFT OUTER JOIN T_Roles r ON c.CurrentRoleID=r.ID
LEFT OUTER JOIN (SELECT
rr.EmployeeID,MAX(rr.ID) AS ID
FROM T_EmployeeRoles rr
LEFT OUTER JOIN (SELECT
e.ID AS EmployeeID, e.Name, r.RoleID AS CurrentRoleID, mr.ID AS EmployeeRoleID
FROM T_Employee e
LEFT OUTER JOIN (SELECT
EmployeeID,MAX(ID) AS ID
FROM T_EmployeeRoles
GROUP BY EmployeeID
) mr ON e.ID=mr.EmployeeID
LEFT OUTER JOIN T_EmployeeRoles r ON mr.ID=r.ID
) cc ON rr.ID=cc.EmployeeRoleID
WHERE cc.EmployeeRoleID IS NULL
GROUP BY rr.EmployeeID
) mr ON c.EmployeeID=mr.EmployeeID
LEFT OUTER JOIN T_EmployeeRoles lr ON mr.ID=lr.ID
LEFT OUTER JOIN T_Roles llr ON lr.RoleID=llr.ID
Batuta, pour quelle classe est ce questin? –
@Batuta, j'ai ajouté une requête à ma réponse qui devrait fonctionner sur SQL Server 2000 –