【问题标题】:How to convert group of SQL records to the single row basing on max and min values?如何根据最大值和最小值将一组 SQL 记录转换为单行?
【发布时间】:2021-10-30 23:07:32
【问题描述】:

我们将员工状态历史记录存储在 SQL Server 表中。有员工 ID(外键)、开始和结束日期以及员工状态列。结束日期列中的 NULL 表示该状态现在处于活动状态。员工可以是活跃的,可以被终止,然后再次活跃。

由于客户端应用程序中的错误,每次更新员工资料时,都会在表中生成新记录,其中开始日期是上一条记录的结束日期(见记录#1,2,3 )。例如,员工 #1 在 1 月 1 日至 4 月 1 日期间处于活动状态,然后他们被解雇了三个月并再次被重新雇用。

Record ID Employee ID Start Date End Date Employee Status
1 1 2019-01-01 2019-02-01 Active
2 1 2019-02-01 2019-03-01 Active
3 1 2019-03-01 2019-04-01 Active
4 1 2019-04-01 2019-07-01 Terminated
5 1 2019-07-01 NULL Active
6 2 2019-01-01 2019-02-01 Active
7 2 2019-01-01 NULL Active
8 3 2019-01-01 NULL Active

我们现在无法修复 UI,因此我们计划经常运行该脚本。 我能够以命令式风格编写带有光标/循环的脚本,但我认为性能不会很好,因为我们有大量的员工状态记录(第一次运行)和很多员工.

我想要一个声明性脚本,它将第 1、2、3 行替换为单行,例如:

Record ID Employee ID Start Date End Date Employee Status
1 1 2019-01-01 2019-04-01 Active

感谢您的建议。

【问题讨论】:

    标签: sql sql-server group-by grouping


    【解决方案1】:

    这是一个间隙和孤岛问题的示例。我建议使用lag() 和累积总和来识别组:

    select min(recordid) as recordid, employeeid, status, min(startdate), max(enddate)
    from (select t.*,
                 sum(case when prev_enddate = startdate then 0 else 1 end) over (partition by employeeid order by startdate) as grp
          from (select t.*,
                       lag(enddate) over (partition by employeeid, status order by startdate) as prev_enddate
                from t
               ) t
          ) t
    group by employeeid, status, grp;
    

    基本上,这会查看同一员工和状态的前一行。如果不与当前行相邻,则当前行开始一个新组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-09
      • 2020-12-14
      • 1970-01-01
      相关资源
      最近更新 更多