2017-02-27 6 views
1

Vereinfachte Struktur.SQL - Start- und Enddatum basierend auf einer anderen Spalte

Ich brauche die beiden Daten zwischen einem Datensatz, der mehrere Male und ich brauchen würde getrennte Reihen für ihre Zeiten

hat in diesem Zustand sein könnte 1.

Der Datensatz einen Aktionstyp von 4 und einen Aktionstyp

beispielsweise für IncidentId = 1

  • Row 1 - Starttime = 2017.01.01 14.00 Uhr (ID: 3) - End Time = 2017.01.01 20.00 Uhr (ID: 5)
  • Zeile 2 - StartTime = 2017-01-01 21:00 (id: 6) - End Time = 2017- 02.01 11.00 Uhr (ID: 9)
 

    CREATE TABLE #returntable 
     ( 
     [incidentid] INT, 
     [starttime] DATETIME, 
     [endtime] DATETIME 
    ) 

    CREATE TABLE #testtableofdoom 
     ( 
     [incidentlogid] INT, 
     [incidentid] INT, 
     [timestamp]  DATETIME, 
     [actiontypeid] INT 
    ) 

    INSERT INTO #testtableofdoom 
      (incidentlogid, incidentid, timestamp, actiontypeid) 
    VALUES (1, 1, '2017-01-01 09:00', 1) 
     , (2, 1, '2017-01-01 11:00', 1) 
     , (3, 1, '2017-01-01 14:00', 4) 
     , (4, 1, '2017-01-01 16:00', 4) 
     , (5, 1, '2017-01-01 20:00', 1) 
     , (6, 1, '2017-01-01 21:00', 4) 
     , (7, 1, '2017-01-02 09:00', 4) 
     , (8, 2, '2017-01-02 10:00', 1) 
     , (9, 1, '2017-01-02 11:00', 1) 
     , (10, 1, '2017-01-02 14:00', 1) 
     , (11, 2, '2017-01-02 15:00', 4) 
     , (12, 1, '2017-01-02 16:00', 1)  
     , (13, 1, '2017-01-02 17:00', 1) 
     , (14, 1, '2017-01-02 18:00', 1) 
     , (15, 2, '2017-01-02 15:00', 1); 

    DROP TABLE #testtableofdoom 

    DROP TABLE #returntable 

+0

Woher wissen Sie, welche 'StartTime' (4) mit welcher 'EndTime' (1) geht? Zum Beispiel: 'IncidentLogID's # 6 & # 7 zeigen beide einen Start für' IncidentID' # 1 an. Woher wissen Sie, ob 'IncidentLogID' # 8 mit # 6 oder # 7 gepaart ist? – 3BK

+0

So werden die Daten formatiert. Wenn ein Ereignis OnHold ist, bleibt es bei ActionTypeId 4. Es bleibt so, bis es nicht länger gehalten wird, aber andere Felder können sich ändern, ohne dass sich die 4 ändert. Die mittleren Datensätze für beispielsweise Zeilen-ID 7 - können in Bezug auf die Rückgabe des Werts ignoriert werden. – Kieran

Antwort

2

verwendet I Tabellenvariablen anstelle von temporären Tabellen und kürzeren Spaltennamen als Sie, aber dies funktioniert:

declare @tt TABLE ( 
    logId INT, iId INT, 
    dt DATETIME, atId INT 

INSERT @tt (logId, iId, 
    dt, atId) values 
(1, 1, '2017-01-01 09:00', 1), 
(2, 1, '2017-01-01 11:00', 1), 
(3, 1, '2017-01-01 14:00', 4), 
(4, 1, '2017-01-01 16:00', 4), 
(5, 1, '2017-01-01 20:00', 1), 
(6, 1, '2017-01-01 21:00', 4), 
(7, 1, '2017-01-02 09:00', 4), 
(8, 2, '2017-01-02 10:00', 1), 
(9, 1, '2017-01-02 11:00', 1), 
(10, 1, '2017-01-02 14:00', 1), 
(11, 2, '2017-01-02 15:00', 4), 
(12, 1, '2017-01-02 16:00', 1), 
(13, 1, '2017-01-02 17:00', 1), 
(14, 1, '2017-01-02 18:00', 1), 
(15, 2, '2017-01-02 15:00', 1) 

Select s.logId startLogid, e.logId endLogId, 
     s.iID, s.dt startTime, e.dt endTime 
from @tt s join @tt e 
    on e.logId = 
     (Select min(logId) from @tt 
     where iId = s.iID 
      and atId = 1 
      and logId > s.logId)     
where s.aTid = 4 
     and ((Select atId from @tt 
      Where logId = 
       (Select Max(logId) from @tt 
       where logId < s.LogId 
       and iId = s.iId)) = 1 
     or Not Exists 
      (Select * from @tt 
      Where logId < s.LogId 
       and iId = s.iID))  

Dies sind die erzeugt folgende:

startLogid endLogId iID startTime    endTime 
----------- ----------- ---- ---------------- ---------------- 
    3   5  1 2017-01-01 14:00 2017-01-01 20:00 
    6   9  1 2017-01-01 21:00 2017-01-02 11:00 
    11   15  2 2017-01-02 15:00 2017-01-02 15:00 

es verwendet einen Self-Join. s steht für den ersten (Start-) Datensatz mit actionType 4 und e für den Endsatz mit Aktionstyp 1. Da logId inkrementiert wird, muss der Enddatensatz den höheren logId als der Startsatz aufweisen und der niedrigste logId höher sein als die Startsätze das hat gleiche iId und ein atId = 1.

Select s.iID, s.dt startTime, e.dt endTime 
from @tt s join @tt e 
    on e.logId = 
     (Select min(logId) from @tt -- lowest log greater than start logId 
     where iId = s.iID   -- same iId 
      and atId = 1   -- with atId = 1 
      and logId > s.logId) -- greater than start logId 

schließlich muss der Startrekord auf jene „4“ Datensätze beschränkt werden, die entweder keine anderen gleichen Vorfall Aufzeichnungen, bevor sie haben oder haben eine „1“ Aufzeichnung unmittelbar vor zu ihm.

where s.aTid = 4 
     and ((Select atId from @tt   -- atId of immed prior = 1 
      Where logId = 
       (Select Max(logId) from @tt 
       where logId < s.LogId 
       and iId = s.iId)) = 1 
     or Not Exists      -- or there is no prior record 
      (Select * from @tt 
      Where logId < s.LogId 
       and iId = s.iID)) 
+0

Angst kein Glück - es bekommt die erste Instanz von ihnen für Vorfall 1, aber bekommt es nicht für die zweite. Insgesamt sollte die Abfrage drei statt zwei Zeilen zurückgeben. Vorfall 1 geht in Reihe 6 bis 8 sowie Reihen 3 bis 5 zurück. Prost – Kieran

+0

Aber Zeile 8 ist für IncidentId = 2. Und was ist mit IncidentId 2 von Zeile 11 bis Zeile 15? –

+0

Vorfall 1 geht in Zeile 6 in die Warteschleife und dann wieder in Zeile 9. Typo. Die folgende Abfrage gibt die erforderlichen Informationen zurück - innerhalb eines Cursors. Idealerweise möchte ich keinen Cursor haben, aber wenn das nötig ist, gehe ich diese Route hinunter. – Kieran

1

so etwas wie das?

select 
d.[timestamp] as StartDate, 
(select top 1 [timestamp] 
from #testTableOfDoom d2 
where d2.incidentid = 1 and d2.[timestamp] > d.[timestamp] and actiontypeid = 1 
order by d2.[timestamp] asc 
) as EndDate 
from 
    (select 
    p.[timestamp], 
    LAG(p.actiontypeid) OVER (ORDER BY incidentlogid asc) PrevValue, 
    p.actiontypeid 
    from #testTableOfDoom p 
    where p.incidentid = 1) d 
where d.actiontypeid = 4 
and d.PrevValue <> 4 
Verwandte Themen