我将通过比较日期值和“更大”或“小于”条件来查询3个表。但我没有写一个关于这个的SQL。日期比较表只有一个字段而不是两个日期的范围,即开始日期和结束日期。表格是:
staff_roster - 包含员工每月记录的主要表格:
staff_no | store | r_date
----------------------------
sf001 | A | 1/10/2016
sf001 | A | 2/10/2016
sf001 | A | 3/10/2016
sf001 | A | 4/10/2016
sf001 | A | 5/10/2016
sf001 | A | 6/10/2016
sf001 | A | 7/10/2016
sf001 | A | 8/10/2016
....
sf002 | A | 1/10/2016
sf002 | A | 2/10/2016
....
staff_posmove - 条件查找的表:
staff_no | p_date | previous_pos | new_pos
---------------------------------------------------
sf001 | 3/10/2016 | Jr sales | clerk
sf001 | 6/10/2016 | clerk | Sr sales
staff_profile
staff_no | position
---------------------
sf001 | Sr sales
sf002 | Jr sales
我想得到一个结果,其中包含表“staff_roster”的列,并附加一列“position”,其值取决于其他2个表。
逻辑是:它将每个staff_roster.r_date与表“staff_posmove”的“p_date”进行比较。如果系统发现“r_date”小于“p_date”的相同人员,则“position”的值为“previous_pos”;但如果它等于或大于,则将“new_pos”作为值。
但问题是“staff_posmove”中可能有多条记录,这会产生重复和错误的结果,因为显然存在重叠条件。
以sf001为例,我的预期结果为:
staff_no | store | r_date | position
-----------------------------------------
sf001 | A | 1/10/2016 | Jr sales
sf001 | A | 2/10/2016 | Jr sales
sf001 | A | 3/10/2016 | clerk
sf001 | A | 4/10/2016 | clerk
sf001 | A | 5/10/2016 | clerk
sf001 | A | 6/10/2016 | Sr sales
sf001 | A | 7/10/2016 | Sr sales
sf001 | A | 8/10/2016 | Sr sales
....
此外,如果系统没有在员工的“staff_posmove”中找到记录进行比较,“位置”应该查找表“staff_profile”,将相关员工的位置放在结果“位置”中:
staff_no | store | r_date | position
-----------------------------------------
sf002 | A | 1/10/2016 | Jr sales
sf002 | A | 2/10/2016 | Jr sales
....
我尝试了类似“CASE WHEN a.staff_no = b.staff_no AND a.r_date< b.p_date THEN CAST(b.previous_pos As varchar(10))”但仍然得到错误的结果。问题可能有点长,但希望你能提供帮助。
答案 0 :(得分:1)
解决此问题的典型方法是使用OUTER APPLY
。这变得更难,因为您没有第一个记录 - staff_posmove
缺少初始记录。
要解决此问题,以下内容始终考虑每个职员的第一条记录,然后使用select
中的逻辑来选择职位:
select r.*,
(case when pm.p_date < r_date then pm.new_pos else pm.old_pos end) as position
from staff_roster r outer apply
(select top 1 pm.*
from (select pm.*,
row_number() over (partition by staff_no order by p_date) as seqnum
from staff_posmove pm
) pm
where p_date < r_date or seqnum = 1 -- always ensure first row is considered
order by pm.p_date desc
) pm
答案 1 :(得分:0)
未经测试:
以下内容应该是每个名单之后的第一步(因此我们接受上一份工作):
Select
r.staff_no, r.store_, r.r_date, p.previous_job
from staff_roster r left join staff_posmove p
on p.staff_no = r.staff_no and r_date < p_date
where row_number() over (partition by r.staff_no, r_date order by p_date) =1
我们将staff_profile添加到其中以获取剩余的那些:
Select
p.staff_no, r.store_, r.r_date, nvl(m.previous_job,p.position)
from staff_profile p join staff_roster r
on p.staff_no = r.staff_no
left join staff_posmove m
on m.staff_no = r.staff_no and r.r_date < m.p_date
where row_number() over (partition by r.staff_no, r.r_date order by m.p_date) =1