SELECT 使用 SQL Server 2008 R2 根据特定条件从下一行中选择的查询?

SELECT query that Selects from Next Row given certain criteria using SQL Server 2008 R2?

我想创建一个 table 在同一行显示员工的雇用日期和随附的任期日期。我在 2 table 秒内使用数据:employeesEEChange

EEChange 有三列很重要:employee_noaction_dateaction_type。对于 'Hire'、'Rehire' 或 'Term',action_type 只会是 'H'、'R' 或 'T'。就我而言,'Hire' 和 'Rehire' 日期是生效日期,'Term' 日期是终止日期。

我可以创建一个 select 查询,将生效日期 (ED) 放在 ED 列中,将期限日期 (TD) 放在 TD 列中。问题是他们不在同一行。我遇到的另一个困难是每个 ED 可能没有关联的 TD。见下文:员工 (EE) 14 于 98 年 5 月 1 日受雇,于 2006 年 9 月 13 日再次受雇,并于 98 年 3 月 23 日任期届满。我不知道为什么我的数据库有一个 Rehire,然后是一个 Hire。就我而言,EE 14 于 98 年 5 月 1 日被聘用,并于 98 年 3 月 23 日任期届满。我假设就业没有中断。

这是我的 tables:

employees:

EE No   Name
6       Anil
12      Viktor
14      Sherry
15      Juan
48      Susan
50      Kevin

EEChange:

EE No   Action_type Action_date
6       H           5/1/1998
6       T           7/26/2010
12      H           5/1/1998
12      R           4/16/2012
14      H           5/1/1998
14      R           9/13/2006
14      T           9/19/2008
15      H           3/23/1998
48      H           7/1/1998
48      R           10/21/2008
48      T           1/3/2009
50      H           7/2/1998
50      R           7/16/2010
50      T           5/1/2012
50      R           12/1/2013
50      T           2/15/2015

我的查询:

SELECT 
    LTRIM(employees.employee_no) as [EE No],
    row_number() OVER (PARTITION BY employees.employee_no ORDER BY EEChange.action_date) AS [Seq],
    EEChange.action_type,
    CASE 
       WHEN EEChange.action_type = 'H' OR EEChange.action_type = 'R' 
         THEN EEChange.action_date
    END AS [Effective Date],
    CASE 
       WHEN EEChange.action_type = 'T' 
         THEN EEChange.action_date
    END AS [Term Date]
FROM 
    dbo.employees employees
LEFT OUTER JOIN 
    dbo.emp_employment_action_changes EEchange ON employees.employee_no = EEChange.employee_no

我添加了 Sequence 列以查看是否可以为每个 [EE No] 排序 action_date 列。我能够这样做,但最终没有成功,并找到了一个 select 可以给我所需结果的查询:ED 和 TD 在同一行。

我的结果:

EE No   Seq action_type Effective Date  Term Date
6       1   H           5/1/1998    
6       2   T                           7/26/2010
12      1   H           5/1/1998    
12      2   R           4/16/2012   
14      1   H           5/1/1998    
14      2   R           9/13/2006   
14      3   T                           9/19/2008
15      1   H           3/23/1998   
48      1   H           7/1/1998
48      2   R           10/21/2008  
48      3   T                           1/3/2009
50      1   H           7/2/1998
50      2   R           7/16/2010
50      3   T                           5/1/2012
50      4   R           12/1/2013
50      5   T                           2/15/2015

想要的结果:

EE No   Name    Effective Date  Term Date
6       Anil    5/1/1998        7/26/2010
12      Viktor  5/1/1998    
14      Sherry  5/1/1998        9/19/2008
15      Juan    3/23/1998   
48      Susan   7/1/1998        1/3/2009
50      Kevin   7/2/1998        5/1/2012
50      Kevin   12/1/2013       2/15/2015

注意 Kevin 在 EEChange table 中有 5 行。我只想要第一个 ED 及其随附的学期日期和下一个 ED 及其随附的学期日期。对于活跃的 EE,将没有最终学期日期。

任何人都可以提供任何帮助。我尝试使用 LEAD() 但它不适用于 SQL Server 2008 R2。我找不到让 LEAD() 跳过 TD 之前序列中出现的 ED 的方法。

所以,看起来你的问题确实是一个间隙和孤岛问题,这意味着你需要找到离散范围的起点和终点。如果我们将操作 H 和 R 都视为范围开始的标记,问题将是找到每个开始日期之后的最早结束日期,该日期晚于该日期。 (有点——我觉得很难描述)。不过,逻辑应该很容易理解。

我用你的示例数据进行了测试,这个查询似乎给出了想要的结果。

with 
a as (
    select 
       e.EENo, e.Name, 
       case 
          when Action_type IN ('R','H') 
          then Action_date 
       end Effective_date, 
       case 
          when Action_type = 'T' 
          then Action_date 
       end Term_date
    from employees e 
    join EEChange ee on e.EENo = ee.EENo
), 
b as (
    select 
       EENo, Name, Effective_date, 
       case 
          when Effective_date is not null 
          then (
             select min(term_date) 
             from a a2  
             where a2.Term_date > a.Effective_date and a2.EENo = a.EENo
             ) 
       end Term_date
    from a
)
select 
    EENo, Name, min(Effective_date) Effective_date, Term_date 
from b 
where Effective_date is not null
group by EENo, Name, Term_date

Sample SQL Fiddle

示例结果:

| EENo |   Name | Effective_date |  Term_date |
|------|--------|----------------|------------|
|    6 |   Anil |     1998-05-01 | 2010-07-26 |
|   12 | Viktor |     1998-05-01 |     (null) |
|   14 | Sherry |     1998-05-01 | 2008-09-19 |
|   15 |   Juan |     1998-03-23 |     (null) |
|   48 |  Susan |     1998-07-01 | 2009-01-03 |
|   50 |  Kevin |     1998-07-02 | 2012-05-01 |
|   50 |  Kevin |     2013-12-01 | 2015-02-15 |
declare @employees  table  (EE int, Name varchar(20));
insert @employees values 
(6,'Anil'),
(12,'Viktor'),
(14,'Sherry'),
(15,'Juan'),
(48,'Susan'),
(50,'Kevin');

declare @EEChange table  (EENo int, Action_type char, Action_date date);
insert @EEChange values 
(6,'H','5/1/1998'),
(6,'T','7/26/2010'),
(12,'H','5/1/1998'),
(12,'R','4/16/2012'),
(14,'H','5/1/1998'),
(14,'R','9/13/2006'),
(14,'T','9/19/2008'),
(15,'H','3/23/1998'),
(48,'H','7/1/1998'),
(48,'R','10/21/2008'),
(48,'T','1/3/2009'),
(50,'H','7/2/1998'),
(50,'R','7/16/2010'),
(50,'T','5/1/2012'),
(50,'R','12/1/2013'),
(50,'T','2/15/2015');
;with CTE AS (
SELECT 
LTRIM(employees.EE) as [EE No],employees.Name,
row_number() OVER (PARTITION BY employees.EE ORDER BY EEChange.action_date) AS [Seq],
EEChange.action_type,
CASE WHEN EEChange.action_type = 'H' OR EEChange.action_type = 'R' THEN
    EEChange.action_date
    END AS [Effective Date],
CASE WHEN EEChange.action_type = 'T' THEN
    EEChange.action_date
    END AS [Term Date]
FROM @employees employees
LEFT OUTER JOIN @EEChange EEchange ON employees.EE = EEChange.EEno
)

select [EE No],Name,MIN([Effective Date])[Effective Date],MIN([Term Date])[Term Date] from CTE 
GROUP BY [EE No],Name
UNION 
select [EE No],Name,MAX([Effective Date])[Effective Date],MAX([Term Date])[Term Date] from CTE 
where Seq > 3
group by [EE No],Name