2012-06-20 33 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万