2010-12-08 67 views
0

我需要制定一個SQL。爲了表達什麼,我需要更好的,我會用以下數據說明了相同的:SQL以獲取每個記錄的頂部詳細信息

不得不重新表述的問題,以更好地理解例如現在

T_Employee 
ID Name 
1 John 
2 Jane 
3 Joe 

T_Roles 
ID RoleName 
1 Clerk I 
2 Clerk II 
3 Manager 
4 Senior Manager 

T_EmployeeRoles 
ID EmployeeID RoleID 
1 1   1 
2 1   2 
3 1   3 
4 2   1 
5 2   2 
6 2   3 
7 2   4 
8 3   3 
9 4   4 

,在SQL選擇應能產生以下輸出:

ID Name Current Role  Last Role 
1 John Manager   Clerk II   
2 Jane Senior Manager Manager 
3 Joe  Senior Manager Manager 

任何幫助或想法非常讚賞。謝謝。

+0

Batuta,這個問題的解答是什麼? – 2010-12-08 18:57:07

+0

@Batuta,我在我的答案中添加了一個查詢,該查詢應該在SQL Server 2000上運行 – 2010-12-09 18:28:47

回答

1

the answer by Alex works for me這裏是一個不同的方式,無需ROW_NUMBER ...

我覺得你的樣本輸出是錯誤的,試試這個:

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 

OUTPUT:

ID   Name  Current Role Last Role 
----------- ---------- --------------- --------------- 
1   John  Manager   Clerk II 
2   Jane  Senior Manager Manager 
3   Joe  Manager   NULL 

(3 row(s) affected) 

當只有一個「當前角色」,因爲員工只工作一個位置,你可以通過在SELECT這樣推「當前角色」到「最後的角色」:

.. 。, ISNULL(llr.RoleName,r.RoleName) AS "Last Role"

編輯

這裏是沒有CTE查詢的版本,因此它的SQL Server 2000上運行,我也換成了變量表與OP的實際表名:

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 
1

我無法在活動實例上驗證這一點,但以下可能正常工作。

;WITH current AS (
    SELECT ID = MAX(er.ID) 
    FROM T_Employees er 
    GROUP BY 
      er.Name 
) 
SELECT c.Name, c.Current, l.Last 
FROM (
      SELECT er.Name, Current = er.Role 
      FROM T_Employees er 
        INNER JOIN current ON current.ID = er.ID 
     ) c 
     LEFT OUTER JOIN (
      SELECT er.Name, Last = er.Role 
      FROM T_Employees er 
        INNER JOIN (
        SELECT ID = MAX(er.ID) 
        FROM T_Employees er 
        WHERE NOT EXISTS (
          SELECT * 
          FROM current 
          WHERE current.ID = er.ID 
          ) 
        GROUP BY 
          er.Name 
       ) last ON last.ID = er.ID 
     ) l ON l.Name = c.Name 
2

你可以只從T_EmployeeRole選擇一切,並添加額外的RoleNumber柱,使用ROW_NUMBER函數的編號爲每個人這樣的角色:

ROW_NUMBER() OVER(PARTITION BY Name ORDER BY ID desc) as RoleNumber

這對每個名稱起動次數,給出最高的ID爲1的RoleNumber。所有RoleNumber = 1將是當前角色,RoleNumber = 2的所有內容都是以前的角色。

http://msdn.microsoft.com/en-us/library/ms186734.aspx

編輯: 要匹配你更新的問題,記下你的數據喬只是一個經理,沒有以前的角色那麼你的榜樣答案不匹配的數據。

select 1 as ID, 'John' as Name 
into #T_Employee 
union select 2, 'Jane' 
union select 3, 'Joe' 

select 1 as ID, 'Clerk I' as RoleName 
into #T_Roles 
union select 2, 'Clerk II' 
union select 3, 'Manager' 
union select 4, 'Senior Manager' 

select 1 as ID, 1 as EmployeeID, 1 as RoleID 
into #T_EmployeeRoles 
union select 2, 1, 2 
union select 3, 1, 3 
union select 4, 2, 1 
union select 5, 2, 2 
union select 6, 2, 3 
union select 7, 2, 4 
union select 8, 3, 3 
union select 9, 4, 4 

select er.ID 
     ,er.EmployeeID 
     ,er.RoleID 
     ,r.RoleName 
     ,ROW_NUMBER() OVER(PARTITION BY er.EmployeeID ORDER BY er.ID desc) as RoleNumber 
into #OrderedRoles 
from #T_EmployeeRoles er 
left join #T_Roles r on r.ID = er.RoleID 

select emp.ID 
     ,emp.Name 
     ,r1.RoleName as CurrentRole 
     ,r2.RoleName as LastRole 
from #T_Employee emp 
left join #OrderedRoles r1 on r1.EmployeeID = emp.ID 
          and r1.RoleNumber = 1 
left join #OrderedRoles r2 on r2.EmployeeID = emp.ID 
          and r2.RoleNumber = 2 
+0

僅適用於SQL Server 2008.我得到的SQL Server是2005年。 – Batuta 2010-12-08 20:34:54

0

我認爲,這將工作:

CREATE TABLE #T_EmployeeRole 
(
    id int identity(1,1), 
    name varchar(10), 
    role varchar(20) 
) 

INSERT INTO #T_EmployeeRole(name, role) 
SELECT 'John', 'Clerk I' UNION ALL 
SELECT 'John', 'Clerk II' UNION ALL 
SELECT 'John', 'Clerk III' UNION ALL 
SELECT 'Mark', 'Junior Developer' UNION ALL 
SELECT 'Mark', 'Developer' UNION ALL 
SELECT 'Mark', 'Senior Developer' UNION ALL 
SELECT 'Alice', 'Accountant I' UNION ALL 
SELECT 'Alice', 'Treasury Analyst I' UNION ALL 
SELECT 'Alice', 'Treasury Analyst II' UNION ALL 
SELECT 'Alice', 'Controller' UNION ALL 
SELECT 'Chris', 'Secretary I' UNION ALL 
SELECT 'Chris', 'Secretary II' UNION ALL 
SELECT 'Eric', 'Analyst I' UNION ALL 
SELECT 'Eric', 'Analyst II' 

select cur.name, cur.role, prev.role 
from #T_EmployeeRole cur 
left outer join #T_EmployeeRole prev on prev.name = cur.name 
    and prev.id = (select max(#T_EmployeeRole.id) from #T_EmployeeRole where #T_EmployeeRole.name = cur.name and #T_EmployeeRole.id <> cur.id) 
where cur.id = (select max(#T_EmployeeRole.id) from #T_EmployeeRole where #T_EmployeeRole.name = cur.name)