开发者

Data Flattening With SQL

This one seems so simple but I cannot figure it out.

I have data stored like this...

 ManagerID     EmployeeID     MangerName
 0             0              Debbie
 1             0              Mar开发者_如何学JAVAk
 2             2              Chris
 3             2              Leo
 4             1              Mar
 5             2              Steve
 6             2              Mar

I want this output to look like

EmployeeID    Manager1    Manager2    Manager3     Manager4
0             Debbie      Mark        Null         Null
1             Mar         Null        Null         Null
2             Chris       Leo         Steve        Mar

I know there can only be four entries so four managers. I know I need to use self joins...but i keep getting back sever rows that look like

0   Debbie  Mark   Mark   Debbie
0   Debbie  Debbie Mark   Debbie    etc.

please help


In SQL Server 2005, Oracle 9 and PostgreSQL 8.4 (or above):

WITH    q AS
        (
        SELECT  employeeId, managerId, ROW_NUMBER() OVER (PARTITION BY employeeID ORDER BY managerId) AS rn
        FROM    mytable
        )
SELECT  q1.employeeId, q1.managerName, q2.managerName, q3.managerName, q4.managerName
FROM    q q1
JOIN    q q2
ON      q2.employeeId = q1.employeeId
        AND q2.rn = 2
JOIN    q q3
ON      q3.employeeId = q1.employeeId
        AND q3.rn = 3
JOIN    q q4
ON      q4.employeeId = q1.employeeId
        AND q4.rn = 4
WHERE   q1.rn = 1

In MySQL:

SELECT  employeeId,
        (
        SELECT  managerName
        FROM    mytable mi
        WHERE   mi.employeeId = md.employeeId
        ORDER BY
                mi.employeeId, mi.managerId
        LIMIT 0, 1
        ) AS manager1,
        (
        SELECT  managerName
        FROM    mytable mi
        WHERE   mi.employeeId = md.employeeId
        ORDER BY
                mi.employeeId, mi.managerId
        LIMIT 1, 1
        ) AS manager2,
        (
        SELECT  managerName
        FROM    mytable mi
        WHERE   mi.employeeId = md.employeeId
        ORDER BY
                mi.employeeId, mi.managerId
        LIMIT 2, 1
        ) AS manager3,
        (
        SELECT  managerName
        FROM    mytable mi
        WHERE   mi.employeeId = md.employeeId
        ORDER BY
                mi.employeeId, mi.managerId
        LIMIT 3, 1
        ) AS manager4
FROM    (
        SELECT  DISTINCT employeeId
        FROM    mytable
        ) md


First I take the distinct list of EmployeeID's, then I join against the table for the MIN ManagerID for that Employee ID. After that it's three LEFT joins each looking for the next MIN ManagerID greater than the previous (if they exist..)

select baseE.EmployeeID, 
       m1.ManagerName as Manager1, 
       ISNULL(m2.ManagerName,'') as Manager2, 
       ISNULL(m3.ManagerName,'') as Manager3, 
       ISNULL(m4.ManagerName,'') as Manager4
from 
       (select distinct EmployeeID 
        from EmployeeManagers 
        order by EmployeeID) baseE
join EmployeeManagers m1 
     on baseE.EmployeeID = m1.EmployeeID
        and m1.ManagerID = (select MIN(ManagerID) 
                            from EmployeeManagers 
                            where EmployeeID = baseE.EmployeeID)
left join EmployeeManagers m2 
          on baseE.EmployeeID = m2.EmployeeID
          and m2.ManagerID = (select MIN(ManagerID) 
                              from EmployeeManagers 
                              where EmployeeID = baseE.EmployeeID 
                              and ManagerID > m1.ManagerID)
left join EmployeeManagers m3 
          on baseE.EmployeeID = m3.EmployeeID
          and m3.ManagerID = (select MIN(ManagerID) 
                              from EmployeeManagers 
                              where EmployeeID = baseE.EmployeeID 
                              and m2.ManagerID IS NOT NULL
                              and ManagerID > m2.ManagerID)
left join EmployeeManagers m4 
          on baseE.EmployeeID = m4.EmployeeID
          and m4.ManagerID = (select MIN(ManagerID) 
                              from EmployeeManagers 
                              where EmployeeID = baseE.EmployeeID 
                              and m3.ManagerID IS NOT NULL
                              and ManagerID > m3.ManagerID)


You can use PIVOT and ROW_NUMBER (SQL Server 2005 and up).

SELECT EmployeeID, [1] Manager1, [2] Manager2, [3] Manager3, [4] Manager4
FROM
(
   SELECT EmployeeID,  ManagerName,
      ROW_NUMBER() OVER (PARTITION BY EmployeeID
                         ORDER BY ManagerID) ManagerSequence
   FROM Managers
) a
PIVOT (MIN(a.ManagerName) FOR a.ManagerSequence in ([1], [2], [3], [4])) b
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜