首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL岛-高级

SQL岛-高级
EN

Stack Overflow用户
提问于 2015-09-20 19:40:06
回答 2查看 157关注 0票数 0

有一张就业表:

代码语言:javascript
复制
CREATE TABLE #Employment (EmployeeName VARCHAR(100), EmploymentStart DATETIME, EmploymentEnd DATETIME)

INSERT INTO #Employment VALUES ('John','2013-08-01','2013-08-07')
INSERT INTO #Employment VALUES ('John','2013-09-08','2014-05-30')
INSERT INTO #Employment VALUES ('John','2014-05-31','2014-09-29')
INSERT INTO #Employment VALUES ('John','2014-09-30','2015-09-17')
INSERT INTO #Employment VALUES ('John','2015-09-18','2015-10-28')
INSERT INTO #Employment VALUES ('John','2015-11-29','2015-12-15')
INSERT INTO #Employment VALUES ('Kelly','2014-07-19','2014-12-30')
INSERT INTO #Employment VALUES ('Kelly','2014-12-31','2015-03-22')
INSERT INTO #Employment VALUES ('Kelly','2015-04-02','2015-09-18')

我需要选择在两个申报日期之间的雇员(连同每一份就业记录):

  1. 没有连续的就业记录,即就业记录已经结束,没有后续的就业或就业已经结束,以下的就业记录与结束的就业记录不相邻(必须至少有一天的间隔)。

  1. 有12个月的连续就业记录,即第一个连续就业记录的岛屿,在申报日期之间结束的就业记录为12个月(这12个月期间属于结束记录范围);雇员可以在以前有就业记录,但没有一个连续12个月;如果雇员遵循连续合同,则不应在另一个申报日期选择连续12个月的连续雇用合同。员工在头12个月的连续工作中得到奖励;每个员工只能得到一次奖励。

因为一名员工可以拥有符合这两种条件的记录,所以我需要为每个选定的记录分配一个SetId,并按条件拆分记录。

宣布日期:

代码语言:javascript
复制
DECLARE @Date_1 DATETIME = '2014-09-14', @Date_2 DATETIME = '2014-09-21'

应该回来

代码语言:javascript
复制
SetId; EmployeeName; EmploymentStart; EmploymentEnd
1; John; 2013-09-08; 2014-05-30  -- Condition 2 fulfilled
1; John; 2014-05-31; 2014-09-29  -- Condition 2 fulfilled

代码语言:javascript
复制
DECLARE @Date_1 DATETIME = '2015-09-15', @Date_2 DATETIME = '2015-09-21'

应该回来

代码语言:javascript
复制
SetId; EmployeeName; EmploymentStart; EmploymentEnd    
1;John;2014-05-31;2014-09-29  -- Condition 2 fulfilled
1;John;2014-09-30,2015-09-17  -- Condition 2 fulfilled
2;John;2015-09-18;2015-10-28  -- Condition 1 fulfilled
3;Kelly;2015-04-02;2015-09-18  -- Condition 1 fulfilled

任何帮助都很感激。

你好,普泽梅克

EN

回答 2

Stack Overflow用户

发布于 2015-09-20 19:58:38

对于第二个条件,您可以尝试使用铅和滞后分析语句将每个记录与其下一个记录连接起来,然后过滤所有有1天以上间隔的记录,然后重新计算未插入的开始日期和结束日期,然后检查声明的开始日期是否更小,您的结束日期和声明的结束日期是否大于您的结束日期(如果我理解您想要做的话),您可以在这里阅读关于铅和滞后的内容:http://www.databasejournal.com/features/mssql/lead-and-lag-functions-in-sql-server-2012.html

第一个条件我不太明白。我想你也可以在那里再用一次,我不明白

票数 1
EN

Stack Overflow用户

发布于 2015-09-20 21:38:02

我建议在返回条件的查询之间使用union all

假设记录并不复杂--嵌套周期和复杂重叠--那么您可以使用lead()和基本逻辑来识别第一个记录:

代码语言:javascript
复制
select e.*, 'First Condition'
from (select e.*,
             lead(EmploymentStart) over (partition by EmployeeName order by EmploymentStart) as next_es
      from #Employment e
      where EmploymentStart <= @Date_2 and EmploymentEnd >= @Date_1
     ) t
where next_es > dateadd(day, 1, EmployementEnd);

第二个问题是差距和岛屿问题,可以用累积和来解决.在Server 2012+中,这实质上是:

代码语言:javascript
复制
select e.EmployeeName, 'Second Condition'
from (select e.*, sum(PeriodStart) over (partition by EmployeeName order by EmploymentStart) as grp
      from (select e.*,
                   (case when lag(EmployementEnd) over (partition by EmployeeName order by EmploymentStart) < datedd(day, -1, EmployeeStart
                         then 1 else 0 end) as PeriodStart
            from #Employment e
            where EmploymentStart <= @Date_2 and EmploymentEnd >= @Date_1
           ) e
     ) e
group by EmployeeName, grp
having dateadd(day, min(EmployeeStart), max(EmployeeStart)) >= 365;

您可能需要修改此查询以处理跨越指定日期跨度的1年期间。最后一个查询是这些(带有适当列)的联合,它只为第二个雇员选择一行(使用row_number() )。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32683504

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档