计算开始日期和结束日期之间的行数

时间:2017-07-08 07:31:30

标签: sql-server tsql

我有一个包含几十万行的表,其中的列包含开始和结束日期时间,如下所示:

ID    StartDateTime              FinishDateTime
--------------------------------------------------------
1     2001-01-01 04:05:06.789    2001-02-03 04:05:06.789
2     2001-01-01 05:05:06.789    2001-01-01 07:05:06.789
3     2001-01-01 06:05:06.789    2001-02-04 07:05:06.789
4     2001-03-01 06:05:06.789    2001-02-03 04:05:06.789

对于每一行,我需要计算“活跃”的数量。开始时的行;与在每行的startdatetime之前和之后开始的count行相同。例如:对于ID = 3,startdatetime介于ID = 1和ID = 2的startdatetime和finishdatetime之间,但不是ID = 3或ID = 4,因此它应返回2.

所需的输出是:

ID    ActiveRows
-----------------
1     0
2     1
3     2
4     0

我可以使用下面的查询让它工作,但运行需要数小时。

select
    ID,
    (select count(1) 
     from table tbl2 
     where tbl2.StartDateTime < tbl.StartDateTime 
       and tbl2.FinishDateTime > tbl.StartDateTime) as 'ActiveRows'
from 
    table tbl

我也试过自己加入桌子,但它似乎也非常慢。

select
    tbl.ID, count(1)
from 
    table tbl
left join table 
    tbl2 on tbl2.StartDateTime < tbl.StartDateTime 
         and tbl2.FinishDateTime > tbl.StartDateTime
group by 
    tbl.ID

执行此计算的最快方法是什么?

1 个答案:

答案 0 :(得分:1)

您可以使用Apply运算符

执行此操作
SELECT tbl.id, 
       oa.activerows 
FROM   yourtable tbl 
       OUTER apply(SELECT Count(tbl2.id) 
                   FROM   yourtable tbl2 
                   WHERE  tbl2.startdatetime < tbl.startdatetime 
                          AND tbl2.finishdatetime > tbl.startdatetime) oa (activerows) 

并且您的原始查询应使用LEFT JOIN来获取ID's 0

要进一步提高效果,您可以在yourtable上创建non clustered索引

Create Nonclustered Index Nix_table on 
      yourtable (startdatetime,finishdatetime) Include (Id)