2016-03-29 5 views
1

Ich habe die folgende Abfrage, wo die Absicht, jeden Datensatz mit der Zeit bis zum nächsten Datensatz zu zeigen, istSQL „Wo“ für leere Unterabfrage

Daten:

gid   time    name 
1010883478 29/03/2016 0:00:02 John 
1010883527 29/03/2016 0:00:04 John 
1010883578 29/03/2016 0:00:06 John 

SQL:

SELECT A.[gid] 
     ,A.[time] 
     ,A.[name] 
     ,(B.[time] - A.[time]) as timeTilNext 
    FROM [location] A CROSS JOIN [location] B 
    WHERE B.[gid] IN (
     SELECT MIN(C.[gid]) 
     FROM [location] C 
     WHERE C.[gid] > A.[gid] AND C.[name] = A.[name]) 
    ORDER BY A.[gid] 

Stromausgang:

gid   time     name timeTilNext 
1010883478 2016-03-29 00:00:02.000 John 1900-01-01 00:00:02.000 
1010883527 2016-03-29 00:00:04.000 John 1900-01-01 00:00:02.000 

Erwartete Ausgabe:

gid   time     name timeTilNext 
1010883478 2016-03-29 00:00:02.000 John 1900-01-01 00:00:02.000 
1010883527 2016-03-29 00:00:04.000 John 1900-01-01 00:00:02.000 
1010883578 2016-03-29 00:00:06.000 John -1 (or whatever) 

Aber es zeigt kein Rekord für die höchste [gid] für einen bestimmten [name] (nur die zweithöchste).

Ich hoffe auf die höchste [gid] -1 für timeTilNext anzuzeigen, um anzuzeigen, dass es keine weiteren Ereignisse gibt.

Irgendwelche Ideen zum Ändern meiner Abfrage?

+1

bitte einige Beispieldaten und dem erwarteten Ergebnis posten. Welche Version von SQL Server verwenden Sie? – Squirrel

+0

@Squirrel fertig! – Zeophlite

+0

Unsicher warum die Downvotes und warum Antworten entfernt wurden? – Zeophlite

Antwort

2

In SQL Server 2012 können Sie LEAD Fensterfunktion, um den Wert der "next" Reihe zu bekommen.

DECLARE @location TABLE ([gid] int, [time] datetime, [name] varchar(50)); 

INSERT INTO @location ([gid], [time], [name]) VALUES 
(1010883478, '2016-03-29 00:00:02', 'John'), 
(1010883527, '2016-03-29 00:00:04', 'John'), 
(1010883578, '2016-03-29 00:00:06', 'John'); 

SELECT 
    A.[gid] 
    ,A.[time] 
    ,A.[name] 
    ,LEAD(A.[time]) OVER(PARTITION BY A.[name] ORDER BY A.[gid]) AS NextTime 
    ,ISNULL(DATEDIFF(second, A.[time], 
     LEAD(A.[time]) OVER(PARTITION BY A.[name] ORDER BY A.[gid])), -1) AS SecondsTillNext 
FROM @location A 
ORDER BY A.[gid]; 

Ergebnis

+------------+-------------------------+------+-------------------------+-----------------+ 
| gid  |   time   | name |  NextTime   | SecondsTillNext | 
+------------+-------------------------+------+-------------------------+-----------------+ 
| 1010883478 | 2016-03-29 00:00:02.000 | John | 2016-03-29 00:00:04.000 |    2 | 
| 1010883527 | 2016-03-29 00:00:04.000 | John | 2016-03-29 00:00:06.000 |    2 | 
| 1010883578 | 2016-03-29 00:00:06.000 | John | NULL     |    -1 | 
+------------+-------------------------+------+-------------------------+-----------------+ 

Wenn die "nächste" Zeile nicht vorhanden ist, würde LEADNULL zurück. Sie können ISNULL() verwenden, um es durch einen Wert ungleich Null zu ersetzen, wenn Sie möchten.

0
select 
*,-1 as 'time until next ' from location t1 
where time=(select max(time) from location t2 where t1.name=t2.name) b 
+0

Könnten Sie dies aktualisieren, um die Überschriften in der Frage zu entsprechen? – Zeophlite

+0

Dies entspricht den Überschriften Ihrer Frage, nur die Änderung ist Tabellenname, ich habe es jetzt geändert – TheGameiswar

0

SELECT A.gid, A.name, A.time, ( (SELECT MIN (B. Zeit) FROM [Ort] B WHERE B. Zeit> A. Zeit UND B. Name = A. Name) - A.time ) als timeTilNext

FROM [Ort] A