2016-06-30 8 views
0

Betrachten Sie eine Tabelle, die eine Warteschlange darstellt, mit einem Zeitstempel von datetime, wenn ein Element hinzugefügt wurde, und einem Zeitpunkt, zu dem es abgeschlossen ist.Wie viele Artikel wurden zu irgendeinem Zeitpunkt nicht verarbeitet?

Die Frage: Wie kann ich effizient für jede gegebene Zeit abfragen, wie viele Elemente in der Warteschlange waren, dh. hinzugefügt, aber nicht abgeschlossen.

Eine Tabelle Probe Beispiel:

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 

Artikel jederzeit hinzugefügt werden können, aber es braucht Zeit für sie abgeschlossen sein.

In dem obigen Beispiel sind 9, 10 und 11 in Bearbeitung, so kann ich leicht abfragen, um zu finden, dass 3 Elemente gerade in der Warteschlange sind. Aber wie frage ich zum Beispiel nach, wie viele Objekte in der Warteschlange waren und zu keiner bestimmten Zeit abgeschlossen wurden?

Ich bin auf der Suche nach einem Ergebnis, das ungefähr so ​​aussieht:

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 

Mein Ziel die Zeiten mit max Anzahl der Elemente in der Warteschlange zu finden ist. Von hier aus könnte ich sagen, dass die Größe des eingereihten Artikels bei 00:33 am höchsten war und dass die Größe des eingereihten Wertes die höchste 00: 12-00: 14 war.

Was ich versucht habe: ich mit WITH experimentiert haben wie in this answer vorgeschlagen. Es funktioniert gut für nur ein Datum, aber wenn ich beide hs.added>= DATEADD(... und hs.completed >= DATEADD( Kriterien verwende, wird die Ausführung, die 0 Sekunden war, nie abgeschlossen. Ich verstehe den Hinrichtungsprozess hier nicht vollständig.

Diese große Tabelle ist in Produktion, und ich möchte eine Abfrage nicht zu lange ausführen lassen.

Edit: Statistik:

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

Sie können immer den genauen Status der Warteschlange finden, indem Sie sie einfach sperren? Holen Sie sich die gewünschten Details und lassen Sie sie los. Zeigen Sie die Ergebnisse. Du bist fertig? Was ist das Problem, das Sie mit diesen genauen Ergebnissen haben? –

+0

Ich möchte einen Überblick darüber erhalten, wie sich die Warteschlange im Laufe der Zeit verhalten hat. – JOG

+0

Ja, Statistiken und Beispiele können gespeichert werden, sind es aber nicht. Ich analysiere vergangene Daten und suche nach Spitzen, die bereits passiert sind. Ich habe keine Admin-Rollen in dieser Produktionsdatenbank. – JOG

Antwort

1

Die grundlegende Abfrage für eine bestimmte Zeit wie folgt aussieht:

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

Für alle Zeiten, können Sie sie nur in einer Unterabfrage zusammen und verbinden sie in:

Um den maximalen Wert zu erhalten, ad d top 1 und order by count(q.id) desc.

+0

Danke, aber immer noch, die Ausführung wird nicht rechtzeitig abgeschlossen. Dieser Tisch ist riesig. Ich aktualisiere die Frage. – JOG

+0

Ich aktualisierte die Frage mit Statistiken und Datumsgenauigkeit. Gibt es hier Leistungsprobleme, die in der Abfrage in Bezug auf die große Anzahl von Zeilen berücksichtigt werden könnten? Sonst habe ich eine Ergebnistabelle mit so vielen Zeilen wie die Quelltabelle. – JOG

0

Für Ihre Überlegung:

Ich benutze ein UDF dynamischen Datumsbereiche zu erzeugen (siehe unten).

Nur eine kurze Notiz, auf ID 8 nehme ich an, Sie hatten einen Tippfehler auf das komplette Datum (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 

Returns

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 

Die UDF - sind da draußen viele Möglichkeiten gibt, oder Sie können sogar ein Datum oder Tally Tabelle verwenden.

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)