2017-02-09 8 views
0

Haben Sie nicht mit einer Lösung unter Verwendung von BigQuery dazu kommen: sagen, dass ich eine Tabelle (nennen wir es TripSpeed) wie folgt aus:Bigquery - Zeilen zwischen Klausel?

DeviceId | TripId | Speed | DateTime 
    5   1  0     
    5   1  8     
    5   1  12     
    5   1  0        
    5   1  2     
    5   2  .................. 
    5   2  ................. 
    6   .......................... 

Ich möchte-org re (aggragate) es in Segmente wie:

DeviceId | TripId | Speed | DateTime 
    5   1  0,8,12    
    5   1  0,2       
    5   2  .................... 
    5   2  ................... 
    6   ............................ 

Weitere Hinweise:

  1. Gruppendaten von DeviceId und tripID

  2. Datumzeit ist einzigartig für jede Zeile und präzise zu Millisekunden, und die Daten müssen innerhalb jeder Gruppe

  3. innerhalb einer gleichen Gruppe von Datumzeit bestellt werden, Geschwindigkeit = 0 Zeile wird der Starter für jedes Segment
  4. Ich habe bereits andere Bereinigungen durchgeführt, so dass es keine fortlaufenden Nullen gibt

Antwort

1

Sie müssen eine Gruppe und dann Aggregation zuweisen. Die Aufgabe ist ziemlich einfach. Es ist die kumulative Summe der Werte, die Null sind. Der Rest ist Aggregation. ABER, das setzt voraus, dass Sie eine Spalte haben, um die Reihenfolge der Zeilen anzugeben. Ich gehe davon aus, dass ist datetime:

select deviceid, tripid, 
     group_concat(speed) 
from (select t.*, 
      sum(case when speed = 0 then 1 else 0 end) over (partition by deviceid, tripid order by datetime) as grp 
     from t 
    ) t 
group by deviceid, tripid, grp 
1

Für BigQuery Standard-SQL

#standardSQL 
WITH TripSpeed AS (
    SELECT 5 AS DeviceId, 1 AS TripId, 0 AS Speed, 1 AS DateTime UNION ALL     
    SELECT 5, 1, 8, 2 UNION ALL     
    SELECT 5, 1, 12, 3 UNION ALL     
    SELECT 5, 1, 0, 4 UNION ALL        
    SELECT 5, 1, 2, 5 UNION ALL     
    SELECT 5, 2, 0, 6 UNION ALL 
    SELECT 5, 2, 1, 7 UNION ALL 
    SELECT 6, 3, 0, 8 
) 
SELECT DeviceId, TripId, STRING_AGG(CAST(Speed AS STRING)) AS Speed, Segment 
FROM (
    SELECT DeviceId, TripId, Speed, 
    COUNTIF(Speed = 0) OVER (PARTITION BY DeviceId, TripId ORDER BY DateTime) AS Segment 
    FROM TripSpeed 
) 
GROUP BY DeviceId, TripId, Segment 
-- ORDER BY DeviceId, TripId, Segment 

Noch eine andere Version ohne analytische Funktion, sondern mit String-Verarbeitung
Irgendwie fühle ich es billiger ist als oben Version sein kann

#standardSQL 
SELECT DeviceId, TripId, Speed 
FROM (
    SELECT DeviceId, TripId, 
    STRING_AGG(
     CONCAT(IF(Speed = 0, '|', ','), CAST(Speed AS STRING)), 
     '' ORDER BY DateTime) AS Speed 
    FROM TripSpeed 
    GROUP BY DeviceId, TripId 
), UNNEST(SPLIT(Speed, '|')) AS Speed 
WHERE Speed <> '' 
-- ORDER BY DeviceId, TripId 

Sie können es mit w testen i mit den gleichen Dummy-Stichprobendaten

WITH TripSpeed AS (
    SELECT 5 AS DeviceId, 1 AS TripId, 0 AS Speed, 1 AS DateTime UNION ALL     
    SELECT 5, 1, 8, 2 UNION ALL     
    SELECT 5, 1, 12, 3 UNION ALL     
    SELECT 5, 1, 0, 4 UNION ALL        
    SELECT 5, 1, 2, 5 UNION ALL     
    SELECT 5, 2, 0, 6 UNION ALL 
    SELECT 5, 2, 1, 7 UNION ALL 
    SELECT 6, 3, 0, 8 
) 
+0

Sie beide arbeiten. Ich bin etwas pingelig auf die Semantik des Kreuzprodukts einer Tabelle und eines Arrays ... scheint schwierig, mehr Spalten in der Geschwindigkeit hinzuzufügen. – foxwendy

+0

Ich wollte Sie nur wissen lassen, dass ich @GordonLinoff antworte, nur weil es vor Ihnen ging und auch funktioniert :) – foxwendy

+0

Sicher, verstanden und kein Problem. Und ... sicher, sie arbeiten beide: o) Ich weiß - Umgang mit "fortgeschrittenen" Features kann komplexer sein - aber wenn Sie ein wenig Zeit investieren, um es zu bekommen - gibt es Ihnen den ganzen neuen Machtbereich: o) fühlen Sie sich frei, zu experimentieren und Fragen zu stellen - wir sind hier, um Ihnen zu helfen, zu lernen –