Wie man Datensätze nach Zeit abtastet

7

Ich habe also eine Tabelle in SQL Server 2014, in der Ereignisse gespeichert sind. Ereignisse werden nicht schneller als einmal pro 10 Sekunden generiert, können jedoch viel langsamer sein (Minuten oder Stunden zwischen Ereignissen). Die Zeit zwischen den Ereignissen ist nicht einheitlich.

Ich möchte die Aufzeichnungen nach Zeit abtasten.
Zum Beispiel möchte ich um eine 10-minütige Abtastung bitten - also würde es Datensatz 1 erfassen, und der nächste Datensatz sollte mindestens 10 Minuten später sein, und der nächste ist mindestens 10 Minuten später als Zeile 2 , und so weiter.

Ich kann dies mit einem iterativen Ansatz erreichen, bei dem jeder Datensatz durchlaufen wird, aber ich möchte, dass die Datenbank die Arbeit erledigt. Das Problem ist, ich weiß nicht, wie ich das mit T-SQL set / window-Anweisungen machen soll.

Kann mir jemand helfen?

Beispieldaten:

EventID | RecordTime
--------+--------------------
   1    | 2017-04-01 12:00:00
   2    | 2017-04-01 12:00:10
   3    | 2017-04-01 12:00:20
   4    | 2017-04-01 12:00:32
   5    | 2017-04-01 12:05:42
   6    | 2017-04-01 12:09:00
   7    | 2017-04-01 12:24:12
   8    | 2017-04-01 12:36:46
   9    | 2017-04-01 12:36:57
  10    | 2017-04-01 15:00:00

Erwünschtes Ergebnis:

EventID | RecordTime
--------+--------------------
   1    | 2017-04-01 12:00:00
   7    | 2017-04-01 12:24:12
   8    | 2017-04-01 12:36:46
  10    | 2017-04-01 15:00:00
  • Die EventIDs 2-6 befinden sich alle innerhalb von 10 Minuten nach Datensatz 1, daher möchte ich sie nicht.
  • EventID 7 ist 24 Minuten 12 Sekunden später als der letzte Datensatz in meiner Ergebnismenge (EventID 1), also möchte ich es.
  • EventID 8 ist 12 Minuten 34 Sekunden später als der letzte Datensatz in meiner Ergebnismenge (EventID 7), also möchte ich es.
  • EventID 9 ist 11 Sekunden später als der letzte Datensatz in meiner Ergebnismenge (EventID 8), daher möchte ich es nicht.
  • EventID 10 ist apx. 2,5 Stunden später als der letzte Datensatz in meiner Ergebnismenge (EventID 9), also möchte ich es.
Sam Axe
quelle
Bitte fügen Sie einige Beispieldaten und das gewünschte Ergebnis hinzu.
McNets
@McNets: Einige Beispieldaten und gewünschte Ergebnisse hinzugefügt. Lassen Sie mich wissen, wenn mehr / andere Daten benötigt werden.
Sam Axe
Was wäre, wenn Sie eine Veranstaltung bei hätten 2017-04-01 12:10:01? Es ist nur 1 Minute 1 Sekunde nach dem vorherigen Ereignis ( 2017-04-01 12:09:00), aber es ist mehr als 10 Minuten nach dem ersten Ereignis ( 2017-04-01 12:00:00). Möchten Sie dieses Ereignis in der Ergebnismenge sehen?
Vladimir Baranov
Es ist einfach, Ereignisse auszuwählen, die den einheitlichen 10-Minuten-Intervallen (12:00, 12:10, 12:20, 12:30, ...) am nächsten kommen, aber das Endergebnis kann Ereignisse enthalten, die gelegentlich weniger als 10 haben Minuten zwischen ihnen. Ist ein solches Ergebnis akzeptabel?
Vladimir Baranov
@VladimirBaranov: Nein, ich möchte die Veranstaltung nicht um 12:10:01 Uhr. Ich stimme zu, die Auswahl von Ereignissen, die festen Intervallen am nächsten kommen, wäre einfach. Ich kann diesen Weg gehen, wenn ich nicht herausfinden kann, wie das geht.
Sam Axe

Antworten:

3

Wenn Sie kein Ereignis bei möchten 12:10:01, ist die Antwort sehr einfach: Verwenden LEADoder LAGvergleichen Sie die Zeitstempel der beiden aufeinander folgenden Zeilen. Beachten Sie jedoch, dass bei einer langen Sequenz von Ereignissen, bei denen jedes Ereignispaar weniger als 10 Minuten voneinander entfernt ist, die Abfrage nur das erste Ereignis dieser Sequenz zurückgibt.

Mit anderen Worten, zwischen zwei Ereignissen muss eine Lücke von mehr als 10 Minuten liegen, um der Ergebnismenge eine Zeile hinzuzufügen.

Beispieldaten

DECLARE @T TABLE(EventID int, RecordTime datetime2(0));
INSERT INTO @T (EventID, RecordTime) VALUES
( 1, '2017-04-01 12:00:00'),
( 2, '2017-04-01 12:00:10'),
( 3, '2017-04-01 12:00:20'),
( 4, '2017-04-01 12:00:32'),
( 5, '2017-04-01 12:05:42'),
( 6, '2017-04-01 12:09:00'),
( 7, '2017-04-01 12:24:12'),
( 8, '2017-04-01 12:36:46'),
( 9, '2017-04-01 12:36:57'),
(10, '2017-04-01 15:00:00');

Abfrage

WITH
CTE
AS
(
    SELECT
        EventID
        ,RecordTime
        ,LAG(RecordTime) OVER (ORDER BY EventID) AS PrevRecordTime
    FROM @T
)
SELECT
    EventID
    ,RecordTime
FROM
    CTE
    CROSS APPLY
    (
        SELECT DATEDIFF(second, PrevRecordTime, RecordTime) AS RecordDiffSeconds
    ) AS CA
WHERE
    RecordDiffSeconds IS NULL
    OR RecordDiffSeconds > 600
ORDER BY EventID;

Ergebnis

+---------+---------------------+
| EventID |     RecordTime      |
+---------+---------------------+
|       1 | 2017-04-01 12:00:00 |
|       7 | 2017-04-01 12:24:12 |
|       8 | 2017-04-01 12:36:46 |
|      10 | 2017-04-01 15:00:00 |
+---------+---------------------+
Vladimir Baranov
quelle
Erstens schätze ich die Hilfe sehr. Zweitens habe ich Ihre Abfrage mit dem Beispielsatz versucht und es werden tatsächlich die richtigen Datensätze zurückgegeben. Bei Anwendung auf meinen realen Datensatz (141 Datensätze über 2 Stunden) werden jedoch inkohärente Ergebnisse zurückgegeben.
Sam Axe
@ SamAxe, danke Sam. Ich würde Ihnen empfehlen, eine weitere Frage mit detaillierteren Beispieldaten zu stellen, die alle interessanten Fälle abdeckt. Zeigen Sie Ihr erwartetes Ergebnis für diese Fälle.
Vladimir Baranov
Ein Follow-up, wenn es Ihnen nichts ausmacht (oder ich kann eine neue Frage stellen, was auch immer sinnvoller ist): Wenn wir die RecordTime von EventID 7 in 2017-04-01 12:10:12(10 Minuten 12 Sekunden nach EventID 1) ändern, wird sie nicht aufgenommen, weil die Die Lücke zum vorherigen Datensatz (EventID 6) beträgt 1 Minute und 12 Sekunden. Es ist jedoch erwünscht, dass es enthalten ist. Irgendwelche Gedanken?
Sam Axe
@ SamAxe, ich denke, dass es besser ist, eine andere Frage zu stellen. Zuerst haben Sie im Kommentar gesagt, dass Sie solche Ereignisse nicht einbeziehen möchten. Jetzt hast du deine Meinung geändert. Stellen Sie eine andere Frage, stellen Sie einen guten Satz von Beispieldaten bereit, die alle Eckfälle abdecken, und erläutern Sie die Logik / welches Ergebnis Sie jeweils benötigen.
Vladimir Baranov
Oh Mann. Ich habe diese Frage in den Kommentaren völlig falsch verstanden. Meine Entschuldigung. Ja, ich werde eine neue Frage stellen.
Sam Axe