考虑一个表示队列的表,其中一个项目被添加时的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
答案 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 1
和order 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)