2016-12-16 4 views
0

wir unser Telefonsystem gerade geändert und alle Mittel werden nun durch alle 15 Minuten protokolliert und wir brauchen 1 Zeile pro EreignisSumme variable Menge von Intervallen zusammen

Tabellenereignis:

empid | code | timestamp | duration 
5111 | 5 | 09:45:00 | 45 
5222 | 2 | 09:58:00 | 120 
5111 | 5 | 10:00:00 | 900 
5111 | 5 | 10:15:00 | 900 
5111 | 5 | 10:15:30 | 30  
5222 | 5 | 11:00:00 | 8 
5222 | 5 | 11:00:05 | 5 

Zeitstempel writen wird Nach der Tat, so ein Zeitstempel um 9:45:00 mit einer Dauer von 45 war von 9:44:15 und da das Intervall um 9:45 aufhörte, wurde es zu dieser Zeit geschrieben, aber ich brauche 9:44:15 Speichern

Ergebnis sollte mir

geben

Das Problem ist, dass die Telefone mit einer maximalen Verzögerung von 2 Stunden gesperrt sind, und wie Sie mit meinem Mitarbeiter sehen können # 5222 verbrachte er 13 Sekunden auf zwei Zeilen ... ich könnte 10 Mal an der gleichen Tabelle teilnehmen. 1 zu vermeiden, wenn es der gleiche Code ist, wo die Endzeit der vorherigen Zeile

dies auf MSSQL die Startzeit der neuen Linie = 2008

Select e.empid 
      ,e.code 
      ,convert(time(0),DATEADD(ss,- e.Duration, e.timestamp)) 
      ,e.duration + isnull(e1.duration,0) + isnull(e2.duration,0) 

    from [event] e 
left join [event] e0 on 
convert(TIME(0),DATEADD(ss,- e.Duration, e.timestamp)) = e0.timestamp 
and 
e.empid = e0.empid 
and 
e.code = e0.code 

left join [event] e1 on 
convert(TIME(0),DATEADD(ss,- e1.Duration, e1.timestamp)) = e.timestamp 
and 
e.empid = e1.empid 
and 
e.code = e1.code 



left join [event] e2 on 
convert(TIME(0),DATEADD(ss,- e2.Duration, e2.timestamp)) = e1.timestamp 
and 
e2.empid = e1.empid 
and 
e2.code = e1.code 

--etc...... 

where isnull(e0.duration,'-10') = '-10' 

Das funktioniert aber bei weitem nicht optimal ist ...

ich würde lieber eine Aggregat-Funktion verwenden, aber ich weiß nicht, wie man es schreibt, da es keinen Comon-Schlüssel gibt, der anders als die letzten Zeitstempel mit neu übereinstimmt - Dauer mit dieser Tabelle!

es ist wichtig zu wissen, dass Agent 5111 am selben Tag wieder auf Code 5 gehen könnte, und ich würde 2 Zeilen für diesen brauchen .... wenn nicht wäre es zu einfach gewesen!

danke im voraus!

Antwort

1

Versuchen Sie es. Ich habe in dem Code kommentiert, aber der grundlegende Algorithmus

  1. Fund rowswhich Fortsetzungen sind also eine Reihe existiert, die einmal übereinstimmt Sie die Dauer subtrahieren
  2. die „Originale“, dh den Beginn jeden Anruf finden durch Subtrahieren die Fortsetzungen
  3. für jedes Original, finden das nächste Original so können wir eine Reihe von Zeiten bestimmen für Fortsetzungen suchen
  4. es kommen alle zusammen und die Gesamtdauer von Fortsetzungen passend zu jedem ursprünglichen
  5. 01.235.164 hinzufügen

Hoffe das hilft, es war eine interessante Herausforderung!


declare @data table 
(
    empid int, 
    code int, 
    [timestamp] time, 
    duration int 
); 

insert into @data values(5111,5,'09:45',45), 
(5222,2,'09:58',120), 
(5111,5,'10:00',900), 
(5111,5,'10:15',900), 
(5111,5,'10:15:30',30), 
(5222,5,'11:00',8), 
(5222,5,'11:00:05',5), 
-- added these rows to include the situation you describe where 5111 goes again on code 5: 
(5111,5,'13:00',45), 
(5111,5,'13:15',900), 
(5111,5,'13:15:25',25); 

-- find where a row is a continuation 
with continuations as (
    select a.empid, a.code, a.[timestamp] , a.duration 
    from @data a 
    inner join @data b on a.empid = b.empid 
     and a.code = b.code 
    where dateadd(ss, -a.duration, a.[timestamp]) = b.[timestamp] 
), 
-- find the "original" rows as the complement of continuations 
originals as 
(
    select d.empid, d.code, d.[timestamp], d.duration 
    from @data d 
    left outer join continuations c on d.empid = c.empid and d.code = c.code and d.timestamp = c.timestamp 
    where c.empid is null 
), 
-- to hand the situation where we have more than one call for same agent and code, 
-- find the next timestamp for each empid/code 
nextcall as (
    select a.*, a2.[timestamp] nex 
    from originals a 
    outer apply (
     select top 1 [timestamp] 
     from originals a2 
     where a2.[timestamp] > a.[timestamp] 
      and a.empid = a2.empid 
      and a.code = a2.code 
     order by a2.[timestamp] desc 
    ) a2 
) 
select o.empid, 
    o.code, 
    dateadd(ss, -o.duration, o.timestamp) as [timestamp], 
    o.duration + isnull(sum(c.duration),0) as duration 
from originals o 
left outer join nextcall n on o.empid = n.empid and o.code = n.code and o.[timestamp] = n.[timestamp] 
left outer join continuations c on o.empid = c.empid 
    and o.code = c.code 
    -- filter the continuations on the range of times based on finding the next one 
    and c.[timestamp] > o.[timestamp] 
    and (n.nex is null or c.[timestamp] < n.nex) 
group by o.empid, 
    o.code, 
    o.duration, 
    o.[timestamp] 
+0

Hallo Danke, die Logik in Ordnung scheint, ich verstehe, wie es funktionieren könnte, ja, es ist eine interessante Herausforderung, in der Tat aber in SQL Server 2008 erhalte ich diese Fehlermeldung: ‚führt‘ ist keine anerkannte integriert im Funktionsnamen. ! Ich war so zuversichtlich, als ich es ausprobiert :(gibt es eine andere Option? und ja, wir sind billig, nicht auf SQL Server 2016 zu aktualisieren! Grrrr –

+0

Aktualisiert, um eine äußere Anwendung anstelle der LEAD zu verwenden. Ich denke, es sollte jetzt im Jahr 2008 funktionieren –

+0

Sie sind ein Genie !!!! Ich werde versuchen, mit einem größeren Maßstab, aber es scheint zu sein, was ich wollte, sieht das Ergebnis gut mit dem Testmuster! FANTASTISCH !!!!!!!! Danke danke! –

Verwandte Themen