2016-06-30 2 views
0

Рассмотрите таблицу, представляющую очередь, с отметкой времени 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.

Что я пытаюсь: Я экспериментировал с WITH, как предлагалось в this answer. Он отлично работает только на одну дату, но когда я использую как критерии hs.added>= DATEADD(..., так и hs.completed >= DATEADD(, выполнение, которое было 0 секунд, теперь считается невозможным. Я не совсем понимаю процесс исполнения здесь.

Этот большой стол находится в производстве, и я не хочу, чтобы запрос выполнялся слишком долго.

Edit: статистика:

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

Вы всегда можете найти точное состояние очереди, просто заблокировав его? Получите детали, которые вы хотите, и отпустите. Покажите результаты. Вы сделали? Какая у вас проблема с этими точными результатами? –

+0

Я хочу получить обзор того, как очередь вела себя со временем. – JOG

+0

Да, статистика и образцы могут быть сохранены, но они не являются. Я анализирую прошлые данные и просматриваю пики, которые уже произошли. У меня нет роли администратора на этом производстве. – JOG

ответ

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; 

Чтобы получить максимальную стоимость, объявление d top 1 и order by count(q.id) desc.

+0

Спасибо, но все же выполнение не завершено своевременно. Эта таблица огромна. Я обновляю вопрос. – JOG

+0

Я обновил вопрос с помощью статистики и точности даты. Существуют ли какие-либо проблемы с производительностью, которые могут быть рассмотрены в запросе, касающемся большого количества строк? В противном случае у меня будет таблица результатов с таким количеством строк, как исходная таблица. – JOG

0

Для вашего рассмотрения:

Я использую UDF для создания динамических диапазонов дат (перечислены ниже).

Просто короткое примечание, на ID 8, я предполагаю, что у вас была опечатка на полную дату (1:16 по сравнению с 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 

ОДС - Есть много вариантов там, или вы можете даже использовать дату или Tally таблицу.

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) 
Смежные вопросы