开发者

Sql Server Find Next Most Recent Changed Record

开发者 https://www.devze.com 2023-02-07 07:15 出处:网络
In my employee history table I\'m trying to find what the salary was and then what it was changed to. Each Salary change inserts a new record because the new salary is considered a new \"job\" so it h

In my employee history table I'm trying to find what the salary was and then what it was changed to. Each Salary change inserts a new record because the new salary is considered a new "job" so it has a start and end date attached. I can select all these dates fine but I keep getting duplicates because I can't seem to compare the current record only against its most recent prior record for that employee. (if that makes sense)

I would like the results to be along the lines of:

Employe Name, OldSalary, NewSalary, ChangeDate(EndDate)
Joe           40,000     42,000     01/10/2011

Example data looks like

EmployeeHistId     EmpId     Name    Salary      StartDate     EndDate
1                  45        Joe     40,000.00   01/05/2011    01/10/2011
2       开发者_如何学Python           45        Joe     42,000.00   01/11/2011    NULL
3                  46        Bob     20,000.00   01/12/2011    NULL


The Swiss army ROW_NUMBER() to the rescue:

with cte as (
select EmployeeHistId     
  , EmpId     
  , Name    
  , Salary      
  , StartDate     
  , EndDate
  , row_number () over (
      partition by EmpId order by StartDate desc) as StartDateRank
from EmployeeHist)
select n.EmpId
  , n.Name
  , o.Salary as OldDalary
  , n.Salary as NewSalary
  , o.EndData as ChangeDate
from cte n
join cte o on o.EmpId = n.EmpId 
  and n.StartDateRank = 1
  and o.StartDateRank = 2;

Use outer join to get employees that never got a raise too.

These kind of queries are always tricky because of data purity issues, if StartDate and EndDate overlap for instance.


I assume the StartDate and EndDate will be same for the new job and previous job. If thats the case try this.

SELECT a.Name AS EmployeeName, b.Salary AS NewSalary a.Salary AS NewSalary, a.StartDate AS ChangeDate
  FROM EMPLOYEE A, EMPLOYEE B
 WHERE a.EmpID = b.EmpID
   AND a.EndDate IS NULL
   AND a.StartDate = b.EndDate


You can use the correlated join operator APPLY which can solve these types of challenges easily

select a.name, curr.salary, prev.salary, prev.enddate
from employee e
cross apply ( -- to get the current
   select top(1) *
   from emphist h
   where e.empid = h.empid  -- related to the employee
   order by startdate desc) curr
outer apply ( -- to get the prior, if any
   select top(1) *
   from emphist h
   where e.empid = h.empid  -- related to the employee
     and h.EmployeeHistId <> curr.EmployeeHistId -- prevent curr=prev
   order by enddate desc) prev  -- last ended
0

精彩评论

暂无评论...
验证码 换一张
取 消