Sql Server 查找下一个最近更改的记录

Posted

技术标签:

【中文标题】Sql Server 查找下一个最近更改的记录【英文标题】:Sql Server Find Next Most Recent Changed Record 【发布时间】: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。 【参考方案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

【讨论】:

以上是关于Sql Server 查找下一个最近更改的记录的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server - 选择最近的记录以生成更改列表

尝试查找 Oracle SQL 中状态字段更改的最近日期

在 SQL Server 中查找最近的日期

sql语句如何查找在一段时间内没有交易记录的用户

按日期查找记录sql Server

如何使用 SQL Server 更新触发器中的原始值更改第二条记录