使用T-SQL,我有一个表[EMP]:

Id SD ED Status Assignment
1 1/1/2020 1/15/2020 A A1
1 1/16/2020 2/1/2020 T null
1 2/2/2020 3/20/2021 A null
1 3/21/2021 10/1/2022 A B6
3 10/15/2022 5/12/2023 A A1
2 1/3/2022 2/1/2022 A B2
2 2/2/2022 11/1/2023 T null
1 10/2/2022 1/1/2023 T null
1 1/2/2023 5/12/2023 A A1
2 11/2/2023 5/12/2023 A A8

ID是员工ID,SD是记录生效开始日期,ED是记录生效结束日期,状态是聘用状态(A=活动,T=终止)

我try 添加两个额外的列,一个是员工的原始雇用日期(每个ID的最早SD,状态=‘A’),另一个是该记录的最近雇用日期(记录后面的最早SD,其中Status=‘T’,即原始雇用日期).

我可以收集原始的雇佣日期:

    SELECT Id, SD, ED, Status, Assignment, OriginalHireDate
    FROM EMP t1
    INNER JOIN (
        SELECT Id, MIN(SD) AS OriginalHireDate
        FROM EMP
        WHERE Status = 'A'
        GROUP BY Id
    ) t2 ON t1.Id = t2.Id

但我可能想得太多了,该如何获取每条记录的最新招聘日期.所需的输出为:

Id SD ED Status Assignment OriginalHireDate RecentHireDate
1 1/1/2020 1/15/2020 A A1 1/1/2020 1/1/2020
1 1/16/2020 2/1/2020 T null 1/1/2020 1/1/2020
1 2/2/2020 3/20/2021 A null 1/1/2020 2/2/2020
1 3/21/2021 10/1/2022 A B6 1/1/2020 2/2/2020
3 10/15/2022 5/12/2023 A A1 10/15/2022 10/15/2022
2 1/3/2022 2/1/2022 A B2 1/3/2022 1/3/2022
2 2/2/2022 11/1/2023 T null 1/3/2022 1/3/2022
1 10/2/2022 1/1/2023 T null 1/1/2020 2/2/2020
1 1/2/2023 5/12/2023 A A1 1/1/2020 1/2/2023
2 11/2/2023 5/12/2023 A A8 1/3/2022 11/2/2023

推荐答案

我知道您的行代表就业开始和结束,如第status列所示:就业以"A"状态开始,可选地以更多的"A"行继续,然后以"T"行结束.

我们可以通过将"最后"状态与当前状态进行比较来识别就业状况;当它从"T"转变为"A"时,新的就业状况就开始了.一旦定义了岛屿,我们就可以只用一个最小窗口来计算开始.

select e.*,
   min(case when status = 'A' then sd end) over(partition by emp) original_hire_date,
   min(case when status = 'A' then sd end) over(partition by emp, grp) recent_hire_date
from (
    select e.*, 
        sum(case when status = 'A' and lag_status = 'T' then 1 else 0 end) over(partition by emp order by sd) grp
    from (
        select e.*, lag(status) over(partition by emp order by sd) lag_status
        from emp e
    ) e
) e
order by id, sd

注意,这可以很好地处理"A"序列(如您的数据所示)和"T"序列,因为它只在"A"/"T"transitions上递增.

Id SD ED Status Assignment lag_status grp original_hire_date recent_hire_date
1 2020-01-01 2020-01-15 A A1 null 0 2020-01-01 2020-01-01
1 2020-01-16 2020-02-01 T null A 0 2020-01-01 2020-01-01
1 2020-02-02 2021-03-20 A null T 1 2020-01-01 2020-02-02
1 2021-03-21 2022-10-01 A B6 A 1 2020-01-01 2020-02-02
1 2022-10-02 2023-01-01 T null A 1 2020-01-01 2020-02-02
1 2023-01-02 2023-05-12 A A1 T 2 2020-01-01 2023-01-02
2 2022-01-03 2022-02-01 A B2 null 0 2022-01-03 2022-01-03
2 2022-02-02 2023-11-01 T null A 0 2022-01-03 2022-01-03
2 2023-11-02 2023-05-12 A A8 T 1 2022-01-03 2023-11-02
3 2022-10-15 2023-05-12 A A1 null 0 2022-10-15 2022-10-15

fiddle

Sql相关问答推荐

SQL查询视图与连接?

Postgres trunc_date删除一个月

在多个柱上连接时,如何确定连接条件?

SQL基于多个值 Select 单行

更新PostgreSQL 15中的JSON值

Select 非重复值并按条件排除行

对表进行多项 Select 以返回最大值和时间

冲突查询的UPDATE时违反非空约束

基于多参数的SQL Server条件过滤

如何根据行状态设置正确的标志

ColdFusion+Docker:未安装SQLSERVER包

如何将insert语句重复n次使一个值递增?

使用 XML 作为 SQL 表

Spark / Hive:如何获取列中正值的百分比?

递归 CTE 附加为行

如何计算两个非周期性时间序列+分组的重叠持续时间

SQL 将 Varchar 转换为日期

Teradata 多个进程的最大进程结束时间捕获

SQL/Postgres:按日期和其他属性对相关性能进行分组

如何在 SQL Server 中参数化 Select top 'n'