SQL选择查询(员工和职位)
我有两张桌子 1表位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
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