在SQL Server中获取下一个和上一个行数据操作

时间:2019-03-15 09:25:40

标签: sql sql-server

我在表中有一个类似于以下格式的数据:

Id  EmployeeCode    JobNumber           TransferNo  FromDate    Todate
--------------------------------------------------------------------------
1   127             1.0                  0          01-Mar-19   10-Mar-19
2   127             1.0                  NULL       11-Mar-19   15-Mar-19 
3   127             J-1                  1          16-Mar-19   NULL
4   136             1.0                  0          01-Mar-19   15-Mar-19
5   136             J-1                  1          16-Mar-19   20-Mar-19
6   136             1.0                  2          21-Mar-19   NULL

我想要这样的结果:

Id  EmployeeCode    JobNumber           TransferNo  FromDate    Todate
--------------------------------------------------------------------------
2   127             1.0                  NULL       01-Mar-19   15-Mar-19 
3   127             J-1                  1          16-Mar-19   NULL
4   136             1.0                  0          01-Mar-19   15-Mar-19
5   136             J-1                  1          16-Mar-19   20-Mar-19
6   136             1.0                  2          21-Mar-19   NULL

这个想法是

  1. 如果连续作业与具有最大ID和最小日期和最大日期的单行相同。例如,对于员工127,第一工作和第二工作编号相同,第二和第三行不同,则将返回第一和第二行,并具有最小fromdate和max todate,并按原样返回第三行。

  2. 如果作业编号与其下一个作业编号不同,则将返回所有行。
    例如:对于136号员工:第一个职位编号与第二个不同,第二个职位与第三个不同,因此将返回所有行。

3 个答案:

答案 0 :(得分:1)

您可以按jobNumber和EmployeeCode进行分组,并使用“最大/最小汇总”功能获取所需的日期

答案 1 :(得分:0)

我怀疑您将从简单的基于集合的查询中得到结果。 因此,我的建议是:在SELECT DISTINCT EmployeeCode ...上声明一个光标。在该光标内,选择带有该EmployeeCode的所有行。在这个集合中工作以找出您的值并从中构造一个结果集。

答案 2 :(得分:0)

这是一个间隙和孤岛问题的示例。这里的解决方案是通过开始定义“岛屿”,因此过程是:

  • 确定何时开始新分组(即与上一行没有重叠)
  • 对开始进行累积总和以获得分组值
  • 汇总

看起来像

select max(id), EmployeeCode, JobNumber,
       min(fromdate), max(todate)
from (select t.*,
             sum(case when fromdate = dateadd(day, 1, prev_todate) then 0 else 1 end) over
                 (partition by EmployeeCode, JobNumber order by id
                 ) as grouping
      from (select t.*,
                   lag(todate) over (partition by EmployeeCode, JobNumber order by id) as prev_todate
            from t
           ) t
     ) t
group by grouping, EmployeeCode, JobNumber;

目前尚不清楚TransferNo的逻辑是什么。最简单的解决方案只是min()max(),但不会返回NULL