2017-03-13 3 views
0

Abstand zwischen den Punkten:Abrufen der ersten und letzten Datensätze jeder Gruppe

Ich habe eine Reihe von GPS-Punkten von jedem Fahrzeug gereist. Ich versuche, die ersten und letzten Aufzeichnungen für jede Reise zu erhalten.

Daten:

VehicleId  TripId   Latitude   Longitude 
    121    131    33.645    -84.424 
    121    131    33.452    -84.409 
    121    131    33.635    -84.424 
    121    131    35.717    -85.121 
    121    131    35.111    -85.111 

In dem obigen Datensatz muss ich die resultset die ersten und letzten Punkte jeder Reise.

VehicleId  TripId   StartLat   StartLong   EndLat   EndLong 
    121    131    33.645    -84.424   35.111   -85.111 

Ich habe versucht, mit der unter Abfrage, aber ich bekomme die Fehlermeldung „Correlated Subqueries, die anderen Tabellen verweisen, werden nicht unterstützt, wenn sie nicht dekorreliert werden können, wie durch sie zu einem effizienten JOIN verwandeln“. Jede Hilfe wäre willkommen.

SELECT 
     a.VehicleId, 
     a.Tripid, 
     a.Latitude AS StartLat, 
     a.Longitude AS StartLong, 
     b.Latitude AS EndLat, 
     b.Longitude AS EndLong, 
     a.DateTime 
    FROMQ 
     `Vehicles` AS a 
    JOIN 
     `Vehicles` AS b 
    ON 
     a.VehicleId = b.VehicleId 
     AND a.Tripid = b.Tripid 
    WHERE 
     a.DateTime IN (
     SELECT 
     MIN(DateTime) 
     FROM 
     `Vehicles` 
     WHERE 
     VehicleId = a.VehicleId 
     AND Tripid = a.Tripid) 
     AND b.DateTime IN (
     SELECT 
     MAX(DateTime) 
     FROM 
     `Vehicles` 
     WHERE 
     VehicleId = a.VehicleId 
     AND Tripid = a.Tripid) 

Antwort

1

Das erste, was in den Sinn kommt, ist row_number():

select v.* 
from (select v.*, 
      row_number() over (partition by vehicleid, tripid order by datetime asc) as seqnum_asc, 
      row_number() over (partition by vehicleid, tripid order by datetime desc) as seqnum_desc 
     from vehicles v 
    ) v 
where seqnum_asc = 1 or seqnum_desc = 1; 

Wenn Sie sie auf der gleichen Zeile wollen:

select vehicleid, tripid, 
     min(datetime) as start_datetime, max(datetime) as end_datetime, 
     min(case when seqnum_asc = 1 then latitude end) as start_latitude, 
     min(case when seqnum_asc = 1 then longitude end) as start_longitude, 
     min(case when seqnum_desc = 1 then latitude end) as end_latitude, 
     min(case when seqnum_desc = 1 then longitude end) as end_longitude 
from (select v.*, 
      row_number() over (partition by vehicleid, tripid order by datetime asc) as seqnum_asc, 
      row_number() over (partition by vehicleid, tripid order by datetime desc) as seqnum_desc 
     from vehicles v 
    ) v 
where seqnum_asc = 1 or seqnum_desc = 1 
group by vehicleid, tripid; 
1

Hier ist eine weitere Option Aggregatfunktionen:

#standardSQL 
WITH Vehicles AS (
SELECT 121 AS VehicleId, 131 AS TripId, 33.645 AS Latitude, -84.424 AS Longitude, DATETIME "2017-03-12 12:00:00" AS DateTime UNION ALL 
SELECT 121, 131, 33.452, -84.409, DATETIME "2017-03-12 12:01:00" UNION ALL 
SELECT 121, 131, 33.635, -84.424, DATETIME "2017-03-12 12:01:32" UNION ALL 
SELECT 121, 131, 35.717, -85.121, DATETIME "2017-03-12 13:00:56" UNION ALL 
SELECT 121, 131, 35.111, -85.111, DATETIME "2017-03-12 20:30:47" 
) 
SELECT 
    VehicleId, 
    TripId, 
    ARRAY_AGG(STRUCT(Latitude, Longitude) 
      ORDER BY DateTime ASC LIMIT 1)[OFFSET(0)] AS start_location, 
    ARRAY_AGG(STRUCT(Latitude, Longitude) 
      ORDER BY DateTime DESC LIMIT 1)[OFFSET(0)] AS end_location 
FROM Vehicles 
GROUP BY 
    VehicleId, 
    TripId; 
0

Mit SQL 2012 können Sie auch

SELECT DISTINCT VehicleId, TripId, 
    FIRST_VALUE(Latitude) OVER (PARTITION BY VehicleId, TripId ORDER BY [Datetime]) AS StartLatitude, 
    LAST_VALUE(Latitude) OVER (PARTITION BY VehicleId, TripId ORDER BY [Datetime] ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS EndLatitude, 
    FIRST_VALUE(Longitude) OVER (PARTITION BY VehicleId, TripId ORDER BY [Datetime]) AS StartLongitude, 
    LAST_VALUE(Longitude) OVER (PARTITION BY VehicleId, TripId ORDER BY [Datetime] ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS EndLongitude 
FROM dbo.Vehicles 
verwenden
Verwandte Themen