2012-06-20 34 views
2

我有2個表SQL SELECT查詢(員工和崗位)

1)表位置

pos_id, pos_description, pos_total(maximum # of employees for that position) 

    1  c++ Developer  3 
    2  Java Developer 2 
    3  DBA    3 

2)表員工

emp_id, emp_pos_id 
1  1 
2  1 
3  2 
4  3 
5  3 
6  3 

我想創建以下報告在SQL Server或Sybase中:

Position Pos. Description  Serial No of Position ID of Employee 
    1  C++ Developer  1      1 
    1  C++ Developer  2      2 
    1  C++ Developer  3      ------------------ 
    2  Java Developer  1      3 
    2  Java Developer  2      ------------------ 
    3  DBA     1      4 
    3  DBA     2      5 
    3  DBA     3      6 

我該如何實現這樣的查詢?

回答

0

所需的基本查詢看起來像:

select p.pos_id, p.pos_description, 
     row_number() over (partition by p.pos_id order by e.emp_id) as SerialNumber, 
     e.emp_id 
from positions p left outer join 
    employees e 
    on p.pos_id = e.emp_pos_id 
order by 1, 2, 3 

的問題是,這不返回空位置。因爲,可以想象,每個職位都可能是空的,在這種情況下需要什麼?

select p.pos_id, p.pos_description, 
     row_number() over (partition by p.pos_id order by p.pos_id) as SerialNumber, 
     NULL as emp_id 
from position p join 
    (select row_number() over (partition by NULL order by pos_id) as seqnum 
     from positions 
    ) as numbers 
    on numbers.seqnum <= p.pos_total 

在這裏,我只是使用表來創建一個數字列表。我加入到這些職位。

下一個查詢使用連接結合了其中兩個:

with byemp as (
    select p.pos_id, p.pos_description, 
      row_number() over (partition by p.pos_id order by e.emp_id) as SerialNumber, 
      e.emp_id 
    from positions p left outer join 
      employees e 
      on p.pos_id = e.emp_pos_id 
    ), 
allpos as (
    select p.pos_id, p.pos_description, 
      row_number() over (partition by p.pos_id order by p.pos_id) as SerialNumber, 
      NULL as emp_id 
    from position p join 
      (select row_number() over (partition by NULL order by pos_id) as seqnum 
      from positions 
      ) as numbers 
      on numbers.seqnum <= p.pos_total 
    ) 
select allpos.pos_id, allpos.pos_description, allpos.SerialNumber, 
     coalesce(byemp.emp_id, allpos.emp_id) as emp_id 
from allpos join 
    byemp 
    on allpos.pos_id = byemp.pos_id and 
     allpos.SerialNumber = byemp.SerialNumber 

基本上,它是保持從allpos所有的位置信息,而是從byemp帶來的EMPID可用時。

+0

那麼該查詢的情況下,失敗時位置的錶行的總數小於pos_total。在將DBA位置的pos_total更新爲4之後,運行上面的示例。它不會爲DBA生成4個空白行,它應該有.. –

+0

非常感謝。我將最後一個JOIN修改爲LEFT JOIN並且它正在工作 – klgr

0

在SQL Server:

;WITH DummyTable AS (
    SELECT 1 AS Value 
    UNION ALL 
    SELECT Value + 1 
    FROM DummyTable 
    WHERE Value < 1000 --This value must be least as large as the largest "maximum # of employees for that position" 
) 
SELECT p.pos_id Position, p.pos_description [Pos. Description], n.Value [Serial No of Position], emp_id [ID of Employee] 
FROM DummyTable n 
    INNER JOIN Positions p 
     ON n.Value <= p.pos_total 
    LEFT JOIN (SELECT emp_id, emp_pos_id, ROW_NUMBER() OVER(PARTITION BY emp_pos_id ORDER BY emp_id) AS emp_position FROM Employees) e 
     ON e.emp_pos_id = p.pos_id 
     AND e.emp_position = n.Value 
ORDER BY p.pos_id, n.Value 
OPTION (MAXRECURSION 0); 
+0

這會工作,假設公司永遠不會有超過1000名員工給定位置... –

0
with mycte 
as 
(
select * from pos p inner join dbo.nums n on p.nums >= n.cnt 
) , 
em as (select empid,empposid,ROW_NUMBER() over(PARTITION by empposid order by empid) as rn  from emp) 
select mc.id as positionid,mc.descr,mc.cnt,isnull(convert(varchar(30),e.empid),'------------') 
from mycte mc 
left join em e on mc.id= e.empposid 
and e.rn = mc.cnt 

試試這個NUMS表只是conating值的表1到100萬