【问题标题】:Count number of rows between start and end date计算开始日期和结束日期之间的行数
【发布时间】:2017-07-09 16:03:39
【问题描述】:

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

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

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

【问题讨论】:

    标签: sql-server tsql


    【解决方案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's0 计数

    为了进一步提高性能,您可以在您的表上创建一个non clustered 索引

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

    【讨论】:

    • 谢谢@prdp。当然要快很多:14:15 为 242,180 行创建了非聚集索引。仍然很想知道是否有更快的方法!
    • @Tim AFAIK,这是满足您要求的三种可能方式。可能会为您的问题增加赏金以引起更多关注。有人可能会想出更好的方法
    猜你喜欢
    • 1970-01-01
    • 2012-04-06
    • 1970-01-01
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多