范围a和b上的分区

时间:2017-03-19 09:37:31

标签: sql sql-server sql-server-2012

我有下表

EmpId   Date    StartOn EndOn
0001    2-Feb-17    590 599
0002    2-Feb-17    600 609
0003    2-Feb-17    610 619
0004    2-Feb-17    626 635
0002    2-Feb-17    630 639
0004    2-Feb-17    640 649
0005    3-Feb-17    630 639

我希望输出像这样

EmpId   Date    StartOn EndOn   Overlapping Num
0001    2-Feb-17    590 599            0    1
0002    2-Feb-17    600 609            0    1
0003    2-Feb-17    610 619            0    1
0004    2-Feb-17    626 635            1    1
0002    2-Feb-17    630 639            1    2
0004    2-Feb-17    640 649            0    1
0005    3-Feb-17    630 639            0    1

这里有一个数据样本

create table Data(
    EmpId nvarchar(4),
    Date date,
    StartOn int,
    EndOn int
  );

insert into Data(EmpId,Date,StartOn,EndOn)
values('0001','02 Feb 2017',590,599),
('0002','02 Feb 2017',600,609),
('0003','02 Feb 2017',610,619),
('0004','02 Feb 2017',626,635),
('0002','02 Feb 2017',630,639),
('0004','02 Feb 2017',640,649),
('0005','03 Feb 2017',630,639)
  

要求:我想知道之间发生了多少重叠   在给定日期StartOnEndOn并按以下方式对这些重叠进行排序   StartOn,例如EmpId(0004与范围626之间的EmpId 0002重叠   和639(重叠发生在范围630和635之间),因此Overlapping列   将保留重叠数,Num将保持数量   按StartOn

排序

这是我试过的

    ;with overlapping as(
    select a.EmpId,a.Date,a.StartOn,a.EndOn,count(b.EmpId) as Num
    from #Data a
    left join #Data b on a.Date = b.Date
    and a.StartOn<=b.EndOn and a.EndOn>=b.StartOn and b.EmpId<>a.EmpId
    group by a.EmpId,a.Date,a.StartOn,a.EndOn
)
select *,rank() over(partition by Date,Num order by StartOn) as Row
from overlapping
order by Date,StartOn,EmpId

我尝试了row_numberrank但未能获得任何所需的结果

3 个答案:

答案 0 :(得分:1)

我倾向于使用exists而不是自我加入。然后,在存在的基础上,累积和来定义&#34;组&#34;然后row_number()

with d as (
      select d.*,
             (case when exists (select 1
                                from #data d2
                                where d2.StartOn <= d.EndOn and
                                      d2.EndOn >= d.StartOn and 
                                      d2.EmpId <> d.EmpId
                               )
                    then 1 else 0
              end) as IsOverlap
      from #data d
     )
select d.*, row_number() over (partition by grp order by StartOn) as num
from (select d.*, sum(IsOverlap) over (order by StartOn) as grp
      from d
     ) d;

但是,我并非100%确定这符合您的需求。当有更多重叠时,结果应该是什么?如果EmpId与他/她自己重叠会怎样?

答案 1 :(得分:0)

这是一种方法:

    Server Version: 76
TWS Time at connection:20170319 05:45:12 EST
<managedAccounts accountsList=DU647841>
<nextValidId orderId=1>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfarm.us>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:cafarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:hfarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:cashfarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfuture>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:jfarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:eufarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usopt>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ushmds.us>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ilhmds>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:euhmds>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:cashhmds>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:fundfarm>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ushmds> 
Contract Values:CAD,CASH,IDEALPRO,IDEALPRO,jpy:
* * * * REQUESTING MARKET DATA * * * *
('global variables:', None, None, None)
last close: 85.07
* * * * CANCELING MARKET DATA * * * *

使用您提供的样本数据,结果为:

;WITH CTE AS
(
    SELECT  EmpId, 
            [Date], 
            StartOn, 
            EndOn,
            ISNULL((
                SELECT 1
                FROM Data t2 
                WHERE t2.EmpId <> t1.EmpId
                AND t2.[Date] = t1.[Date]
                AND t2.StartOn < t1.EndOn
                AND t2.EndON > t1.StartOn
            ), 0) As Overlapping
    FROM Data t1
)

SELECT  EmpId, 
        [Date], 
        StartOn, 
        EndOn,
        Overlapping,
        ISNULL(NULLIF(Overlapping, 0) + LAG(Overlapping) OVER (ORDER BY [Date], StartOn, EndOn), 0) As Num
FROM CTE

Live demo on rextester

答案 2 :(得分:0)

我设法通过在分区

中添加iif来解决它
;with overlapping as(
    select a.EmpId,a.Date,a.StartOn,a.EndOn,count(b.EmpId) as Num
    from #Data a
    left join #Data b on a.Date = b.Date
    and a.StartOn<=b.EndOn and a.EndOn>=b.StartOn and b.EmpId<>a.EmpId
    group by a.EmpId,a.Date,a.StartOn,a.EndOn
)
select *,row_number() over(partition by Date,iif(Num=0,StartOn,Num) order by StartOn) as Row
from overlapping
order by Date,StartOn,EmpId

但我正在寻找更好的解决方案