SQL选择查询(员工和职位)

SQL选择查询(员工和职位),sql,sybase,Sql,Sybase,我有两张桌子 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

我有两张桌子

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

如何实现这样的查询?

您需要的基本查询如下所示:

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
基本上,它保留所有POS的所有位置信息,但在可用时从byemp引入empid。

在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);

试试看,这个nums表只是一个值为100万到100万的表,如果position表中的行总数小于position表中的行总数,那么这个查询就会失败。将DBA职位的pos_总数更新为4后,运行上述示例。它不会为DBA生成4个空的空行,这是它应该有的。非常感谢。我将最后一个联接修改为左联接,并且它正在工作。假设一家公司在给定的职位上的员工不可能超过1000人,这将起作用。。。
 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