2017-03-13 11 views
1

Lasst uns gehe ich davon aus Zeitstempel-Daten in der Tabelle folgenden haben:am nächsten Zeitstempel Wählen Sie alle 30 Minuten

Id     Timestamp 
-------------------- ----------------------- 
1     2016-09-19 13:17:24.000 
2576     2016-09-19 13:47:24.000 
4945     2016-09-19 14:17:24.000 
7538     2016-09-19 14:47:24.000 
10016    2016-09-19 15:17:24.000 
10570    2016-09-19 15:24:51.000 
11968    2016-09-19 15:47:55.000 
11990    2016-09-19 15:48:08.000 
13648    2016-09-19 16:18:08.000 
14742    2016-09-19 16:36:55.000 

Jetzt möchte ich am nächsten Zeitstempel von start_date wählen und

gefunden für Zeitstempel + 30 min

für nächste nächste Zeitstempel suchen kurzes Beispiel:

start_date = 2016-09-19 13:00:00.000 
end_date = 2016-09-19 16:00:00.000 
Now it should find record: 
2016-09-19 13:17:24.000 
Now we add 30 minutes to found date, so we will search closest timestamp for 13:47:23.000 and so on until date = 16:00. 

Hinweis: es sollte am nächsten Näherungswert sein, so kann es sein, weniger als 30 min diff

Voll Beispiel:

start_date = 2016-09-19 13:00:00.000 
end_date = 2016-09-19 16:00:00.000 

Id     Timestamp 
-------------------- ----------------------- 
1     2016-09-19 13:17:24.000 
2576     2016-09-19 13:47:24.000 
4945     2016-09-19 14:17:24.000 
7538     2016-09-19 14:47:24.000 
10016    2016-09-19 15:17:24.000 
11968    2016-09-19 15:47:55.000 

Wie ich das erreichen kann? Ich würde lieber vermeiden, Cursor zu verwenden, es kann von

+0

Ich sehe nicht, wie 11968 Ihre Kriterien erfüllt. Es ist 00:30:31 Minuten nach dem ersten Zeitstempel. –

+0

11968 ist die erste> = 30 Minuten nach der vorherigen (10016). – TDP

Antwort

2

Wenn Id und Timestamp in der gleichen Reihenfolge erscheinen den folgenden Code (das ist keine Rekursion oder CTE):

SELECT * 
INTO #TempTable 
FROM (VALUES 
    (1,  CAST('2016-09-19 13:17:24.000' AS DATETIME)), 
    (2576, CAST('2016-09-19 13:47:24.000' AS DATETIME)), 
    (4945, CAST('2016-09-19 14:17:24.000' AS DATETIME)), 
    (7538, CAST('2016-09-19 14:47:24.000' AS DATETIME)), 
    (10016, CAST('2016-09-19 15:17:24.000' AS DATETIME)), 
    (10570, CAST('2016-09-19 15:24:51.000' AS DATETIME)), 
    (11968, CAST('2016-09-19 15:47:55.000' AS DATETIME)), 
    (11990, CAST('2016-09-19 15:48:08.000' AS DATETIME)), 
    (13648, CAST('2016-09-19 16:18:08.000' AS DATETIME)), 
    (14742, CAST('2016-09-19 16:36:55.000' AS DATETIME))) 
    AS T (Id, [Timestamp]) 

DECLARE 
    @StartDate DATETIME = '2016-09-19 13:00:00.000', 
    @EndDate DATETIME = '2016-09-19 16:00:00.000'; 

SELECT MIN(Id) AS Id, MIN([Timestamp]) AS [Timestamp] 
FROM #TempTable 
WHERE [Timestamp] BETWEEN @StartDate AND @EndDate 
GROUP BY 
    CAST([Timestamp] AS DATE), -- day 
    DATEPART(hour, [Timestamp]), -- hour 
    DATEPART(minute, [Timestamp])/30 -- half an hour (0 or 1) 
ORDER BY Id 

Wenn wir nicht haben solche Bestellung und die gleiche Timestamp mehrere Male erscheinen könnte, könnte CTE verwendet werden:

DECLARE 
    @StartDate DATETIME = '2016-09-19 13:00:00.000', 
    @EndDate DATETIME = '2016-09-19 16:00:00.000'; 

WITH TargetTimestamps AS 
(
    SELECT MIN([Timestamp]) AS MinTimestamp 
    FROM #TempTable 
    WHERE [Timestamp] BETWEEN @StartDate AND @EndDate 
    GROUP BY 
     CAST([Timestamp] AS DATE), -- day 
     DATEPART(hour, [Timestamp]), -- hour 
     DATEPART(minute, [Timestamp])/30 -- half an hour (0 or 1) 
) 
SELECT MIN(Id) AS Id, MinTimestamp 
FROM #TempTable 
JOIN TargetTimestamps ON [Timestamp] = MinTimestamp 
GROUP BY MinTimestamp -- use grouping to avoid duplicates for the same [Timestamp] 
ORDER BY MinTimestamp 
+0

Wahrscheinlich habe ich die Anforderungen nicht gut spezifiziert. Ihre Code-Suche nach dem kleinsten Zeitstempel für alle 30 min Teile, z. Es gibt folgende Werte zurück (Tag sind gleich): "13:24:00, 13:57:00, 14:00:00, 14: 30: 00", aber ich möchte den nächsten Zeitstempel basierend auf dem vorherigen Zeitstempel finden. Also nach 13:57:00 sollte es nach dem nächsten (nicht kleinsten) Zeitstempel für 13:57:00 + 30min suchen (wie 14:24 oder 14:33) – mkul

0

getan werden Sie können dies in einer einzelnen Abfrage tun. Ich bin nicht 100% sicher, was Sie tatsächlich brauchen (Ihr Beispiel scheint die Aussage zu kontrahieren). Aber hier ist die allgemeine Struktur:

with x as (
     select min(timestamp) as first_timestamp 
     from t 
     where timestamp >= @start_date 
    ) 
select t.* 
from t join 
    x 
    on t.timestamp >= x.first_timestamp and 
     t.timestamp < dateadd(minute, 30, x.first_timestamp); 
+0

Ich denke, er will die erste nach dem Start, gefolgt von jeder nächsten, die mindestens 30 Minuten nach der vorher gefundenen ist. Rekursiver CTE? – TDP

0

Rekursion wird diktiert von

nächste nächste Zeitstempel gefunden für Zeitstempel + 30 min

Leider CTE nicht erlaubt TOP (1) im rekursiven Teil. Workaround ist die Verwendung row_number() ... = 1

SELECT * 
INTO #TempTable 
FROM (VALUES 
    (1,  CAST('2016-09-19 13:17:24.000' AS DATETIME)), 
    (2576, CAST('2016-09-19 13:47:24.000' AS DATETIME)), 
    (4945, CAST('2016-09-19 14:17:24.000' AS DATETIME)), 
    (7538, CAST('2016-09-19 14:47:24.000' AS DATETIME)), 
    (10016, CAST('2016-09-19 15:17:24.000' AS DATETIME)), 
    (10570, CAST('2016-09-19 15:24:51.000' AS DATETIME)), 
    (11968, CAST('2016-09-19 15:47:55.000' AS DATETIME)), 
    (11990, CAST('2016-09-19 15:48:08.000' AS DATETIME)), 
    (13648, CAST('2016-09-19 16:18:08.000' AS DATETIME)), 
    (14742, CAST('2016-09-19 16:36:55.000' AS DATETIME))) 
    AS T (Id, [Timestamp]) 

DECLARE 
    @StartDate DATETIME = '2016-09-19 13:00:00.000', 
    @EndDate DATETIME = '2016-09-19 16:00:00.000'; 


with found as (
    select top(1) *, r = 1 
    from #TempTable 
    where [Timestamp] between @StartDate and @EndDate 
    order by [Timestamp] 
    union all 
    select t.*, r = cast(row_number() over (partition by f.r order by t.[Timestamp]) as int) 
    from found f 
    join #TempTable t on t.[Timestamp] >= dateadd(minute, 30, f.[Timestamp]) 
     and t.[Timestamp] between @StartDate and @EndDate 
     and f.r=1 
) 
select * 
from found 
where r = 1 
order by [Timestamp] 
Verwandte Themen