【问题标题】:Sql Server Find Next Most Recent Changed RecordSql Server 查找下一个最近更改的记录
【发布时间】:2011-01-27 20:24:50
【问题描述】:

在我的员工历史记录表中,我试图找出薪水是多少,然后又变成了什么。每次薪水更改都会插入一条新记录,因为新薪水被认为是新的“工作”,因此它附有开始和结束日期。我可以很好地选择所有这些日期,但我不断重复,因为我似乎无法将当前记录与该员工最近的先前记录进行比较。 (如果有道理的话)

我希望结果类似于:

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

示例数据看起来像

EmployeeHistId     EmpId     Name    Salary      StartDate     EndDate
1                  45        Joe     40,000.00   01/05/2011    01/10/2011
2                  45        Joe     42,000.00   01/11/2011    NULL
3                  46        Bob     20,000.00   01/12/2011    NULL

【问题讨论】:

  • 你能指望每个 EmpID 只有一个 NULL EndDate 吗?
  • 但是你可以让所有 EndDates 都为空(员工离开),这会使它作为谓词无效。哪个版本的 SQL Server?
  • 只有每个员工最近的记录才会有一个空结束日期。它的 sql server 2005。

标签: sql sql-server tsql


【解决方案1】:

瑞士军队 ROW_NUMBER() 进行救援:

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;

使用外部联接来获取从未加薪的员工。

由于数据纯度问题,这类查询总是很棘手,例如,如果 StartDate 和 EndDate 重叠。

【讨论】:

  • 开始日期和结束日期不应重叠,但我不能保证。该解决方案是否涵盖了这种可能性?
  • 我将发布与您相同的解决方案,但有一个不同之处:不是按 StartDate 排序,而是按 CASE EndDate WHEN NULL THEN 0 ELSE 1 END, EndDate DESC 排序,这样您将获得最新的 EndDate。重叠无关紧要,您将包括NULL
【解决方案2】:

我假设新工作和以前工作的 StartDate 和 EndDate 相同。 如果是这样的话,试试这个。

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

【讨论】:

  • 我喜欢你的方法,但从他的样本数据来看,情况并非如此......
  • 可能是where a.employeehistid = b.employeehistid - 1
【解决方案3】:

您可以使用关联连接运算符APPLY,它可以轻松解决这些类型的挑战

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

【讨论】:

    猜你喜欢
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    相关资源
    最近更新 更多