在任何给定时间,未处理多少项?

时间:2016-06-30 00:30:56

标签: sql tsql sql-server-2008-r2 aggregation

考虑一个表示队列的表,其中一个项目被添加时的datetime时间戳,以及一个完成时间的时间戳。

问题: 如何有效地查询任何给定的时间,队列中有多少项,即。添加但未完成。

表格示例示例:

id value added                     completed
6  1     2016-01-01 00:00:12.345   2016-01-01 00:01:12.345
7  500   2016-01-01 01:12:12.345   2016-01-01 01:15:12.345
8  1     2016-01-01 01:12:12.345   2016-01-01 02:16:12.345
9  2     2016-01-01 01:33:12.345   NULL
10 2     2016-01-01 01:33:12.345   NULL
11 2     2016-01-01 01:33:12.345   NULL

可以随时添加项目,但需要时间才能完成。

在上面的示例中,9,10和11正在处理中,因此我可以轻松查询现在正在查找3个项目。但是,如何查询以查找有多少项目在队列中并且在任何给定的过去时间内未完成?

我正在寻找一个看起来像这样的结果:

date        time          count       sum value
2016-01-01  00:00:00.000  1           1
2016-01-01  00:12:00.000  2           501
2016-01-01  00:13:00.000  2           501
2016-01-01  00:14:00.000  2           501
2016-01-01  00:15:00.000  1           1
2016-01-01  00:33:00.000  3           6

我的目标是找到队列中最大项目数的时间。从这里我可以说排队的项目大小在00:33最高,排队的值大小最高00:12-00:14。

我尝试过的内容:我已尝试使用this answer中建议的WITH。它只适用于一个日期,但是当我同时使用hs.added>= DATEADD(...hs.completed >= DATEADD(条件时,0秒的执行现在看来永远不会完成。我并没有完全掌握这里的执行过程。

这个大表正在生产中,我不希望查询执行时间太长。

修改:统计信息

COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH IS_NULLABLE
ID          int       NULL                     NO
added       datetime  NULL                     NO
completed   datetime  NULL                     YES
value       int       NULL                     NO

CONSTRAINT_NAME
PK_Queue

name                type_desc     is_unique is_primary_key
PK_Queue            CLUSTERED     1         1
IX_Queue_completed  NONCLUSTERED  0         0
IX_Queue_added      NONCLUSTERED  0         0

rows       data
6 000 000  15 000 000 KB

2 个答案:

答案 0 :(得分:1)

基本查询在给定时间内看起来像这样:

select count(*), sum(q.value)
from queue q
where @datetime >= q.added and
      (@datetime < q.completed or q.completed is null);

在任何时候,您都可以将它们放在子查询中并将它们加入:

select dt.dt, count(q.id), sum(q.value)
from (select q.added as dt from queue q union select q.completed from queue q
     ) dt left join
     queue q
     on dt.dt >= q.added and (dt.dt < q.completed or q.completed is null)
group by dt.dt
order by dt.dt;

要获得最大值,请添加top 1order by count(q.id) desc

答案 1 :(得分:0)

供您考虑:

我使用UDF生成动态日期范围(如下所示)。

请注意,在ID 8上,我假设您在完整日期输入了错字(1:16 vs 2:16)。

Declare @Table table (id int, value int,Added datetime,complete datetime)
Insert into @Table values
(6,  1,  '2016-01-01 00:00:12.345','2016-01-01 00:01:12.345'),
(7,  500,'2016-01-01 01:12:12.345','2016-01-01 01:15:12.345'),
(8,  1  ,'2016-01-01 01:12:12.345','2016-01-01 01:16:12.345'),
(9,  2  ,'2016-01-01 01:33:12.345',NULL),
(10, 2  ,'2016-01-01 01:33:12.345',NULL),
(11, 2  ,'2016-01-01 01:33:12.345',NULL)


Declare @DateR1 DateTime = '2016-01-01 00:00'
Declare @DateR2 DateTime = '2016-01-01 01:35'
Declare @DatePart varchar(25) = 'MI'
Declare @DateIncr int = 1


Select KeyDate
      ,Count = sum(isnull(Sign(B.Value),0))
      ,Value = isnull(sum(Value),0)
   From (Select KeyDate = RetVal From  [dbo].[udf-Create-Range-Date](@DateR1,@DateR2,@DatePart,@DateIncr)) A
   Left Join @Table  B
   on KeyDate between added and IsNull(complete,@DateR2)
  Group By KeyDate
  Having sum(value)>0  -- Optional for zero supression
  Order By KeyDate

返回

KeyDate                 Count  Value
2016-01-01 00:01:00.000 1      1
2016-01-01 01:13:00.000 2      501
2016-01-01 01:14:00.000 2      501
2016-01-01 01:15:00.000 2      501
2016-01-01 01:16:00.000 1      1
2016-01-01 01:34:00.000 3      6
2016-01-01 01:35:00.000 3      6

UDF - 有很多选项,你甚至可以使用日期或理货表。

CREATE FUNCTION [dbo].[udf-Create-Range-Date] (@DateFrom datetime,@DateTo datetime,@DatePart varchar(10),@Incr int)

Returns 
@ReturnVal Table (RetVal datetime)

As
Begin
    With DateTable As (
        Select DateFrom = @DateFrom
        Union All
        Select Case @DatePart
               When 'YY' then DateAdd(YY, @Incr, df.dateFrom)
               When 'QQ' then DateAdd(QQ, @Incr, df.dateFrom)
               When 'MM' then DateAdd(MM, @Incr, df.dateFrom)
               When 'WK' then DateAdd(WK, @Incr, df.dateFrom)
               When 'DD' then DateAdd(DD, @Incr, df.dateFrom)
               When 'HH' then DateAdd(HH, @Incr, df.dateFrom)
               When 'MI' then DateAdd(MI, @Incr, df.dateFrom)
               When 'SS' then DateAdd(SS, @Incr, df.dateFrom)
               End
        From DateTable DF
        Where DF.DateFrom < @DateTo
    )

    Insert into @ReturnVal(RetVal) Select DateFrom From DateTable option (maxrecursion 32767)

    Return
End

-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','YY',1) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','DD',1) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-31','MI',15) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-02','SS',1)