如何检查一个表中组合在一起的几行是否符合某个标准

时间:2018-04-23 19:05:34

标签: sql-server tsql

对于SQL和DB而言,我并不是太擅长,但我正在努力解决相当严重的问题(与我的知识相比):

我有一张表,其中包含了所有员工的所有缺席情况,这些表是由病假的叶子引起的,其中列表示'date_from',date_to'和缺席的'持续时间'。我需要选择每个病假的员工至少连续30天。我在这里发现问题的一点是,一个人可以提交在DB中注册的多个病假文件。这意味着一个人可以连续30天休病假,但是当检查多个具有特定“employee_id”的记录时,该信息将被确认。

以示例来说明:

Employee_id | Name        | Date_from   | Date_to     | Duration
------------+-------------+-------------+-------------+----------
   00001    | John Newbie | 01-Apr-2018 | 25-Apr-2018 | 25 days
   00001    | John Newbie | 26-Apr-2018 | 03-May-2018 |  8 days

在这个例子中,asbecne总计最多33天,这个员工应该通过查询返回,而这两个记录之间至少有一天差距(例如,员工出现在工作中4月26日,4月27日缺席),该员工不应出现在报告中。

我不知道如何开始。我感谢任何帮助。

谢谢

2 个答案:

答案 0 :(得分:3)

这被称为“差距和岛屿”问题。通过开始和结束日期使它变得有点复杂。

想法是确定岛屿的起点。您可以通过开始没有重叠然后使用累积总和来识别组来完成此操作。其余的只是聚合:

select employee_id, min(date_from) as date_from, max(date_to) as date_to
from (select a.*, sum(flag_start) as grp
      from (select a.*,
                   (case when exists (select 1
                                      from absences a2
                                      where a2.employee_id = a.employee_id and
                                            a2.date_from <= a.date_to and
                                            a2.date_to >= a.date_from
                                     )
                         then 0 else 1
                    end) as flag_start
            from absences a
           ) a
     ) a
group by employee_id, grp
having max(date_to) >= date_add(day, 30, min(date_from));

答案 1 :(得分:0)

在这种情况下,SQL Server 2012提供的

Lag函数非常有用

select
    Employee_id, Name, Date_from = min(Date_from), Date_to = max(Date_to), Duration = sum(Duration)
from (
    select
        Employee_id, Name, Date_from, Date_to, Duration
        , grp = sum(iif(datediff(dd, previous, Date_from) = 1, 0, 1)) over (partition by Employee_id order by Date_from)
    from (
        select 
            *, previous = lag(Date_to) over (partition by Employee_id order by Date_from)
        from myTable
    ) t
) t
group by Employee_id, Name, grp
having sum(Duration) >= 30