2017-11-27 5 views
1

Gibt es eine Möglichkeit, das Verhalten von FILTER (http://modern-sql.com/feature/filter) in Standard SQL BigQuery zu emulieren?Filterpartitionen im Fenster - Berechnung der Ereignisrezenz in BigQuery

Was ich brauchen würde, zu tun ist:

SELECT MAX(date) FILTER (WHERE event_happend = 1) OVER ( PARTITION BY user_id ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) FROM ...

Im Wesentlichen Ich brauche das jüngste Datum ein bestimmtes Ereignis zum Zeitpunkt der aktuellen Zeile vor aufgetreten auszuarbeiten. Spalte event_happened nimmt Werte 0 und 1 und ich brauche das letzte Datum, an dem das Ereignis aufgetreten ist (event_happened = 1) vor dem Datum der aktuellen Zeile.

+0

Warum nicht RANGE anstelle von ROWS verwenden? Dann können Sie den Wert der aktuellen Zeile ausschließen. –

+0

@ElliottBrossard Danke für Ihren Vorschlag - aber ich fürchte, ich verstehe nicht ganz, wie mir die Verwendung von RANGE helfen würde. Könnten Sie bitte erläutern? Ich fügte meiner Frage zur Klärung auch Folgendes hinzu: "Die Spalte event_happened nimmt die Werte 0 und 1 und ich brauche das letzte Datum, an dem das Ereignis aufgetreten ist. Event_happened = 1 vor dem Datum der aktuellen Zeile." – user3531907

+0

@ElliottBrossard Ich aktualisierte auch den Namen der Datumsspalte in meiner Frage - meine erste Wahl dort war verwirrend – user3531907

Antwort

1

Gibt es eine Möglichkeit, das Verhalten von FILTER zu emulieren?

#standardSQL 
SELECT 
    MAX(IF(event_happend = 1, date, null)) 
    OVER (
    PARTITION BY user_id 
    ORDER BY date ASC 
    ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING 
) 
    FROM 
    ... 
+0

Dies wird möglicherweise die falsche Antwort geben, wenn es mehrere der gleichen "Datum" Wert im Fenster gibt - siehe meine Lösung mit 'RANGE'. –

+0

: o) 'MAX (IF (event_happend = 1, Datum, null))' ist der Kern der Antwort über 'FILTER' - Ich habe nichts anderes von der ursprünglichen Frage als exakte Logik geändert, die von OP erwartet wird, ist nicht wirklich klar –

+0

Ich stimme zu, aber das OP hat "vor dem Datum der aktuellen Reihe" angegeben, also schien es wichtig, dies zu berücksichtigen. –

2

Try this:

#standardSQL 
WITH SampleData AS (
    SELECT 1 AS user_id, DATE '2017-11-02' AS date, 1 AS event_happend UNION ALL 
    SELECT 1, DATE '2017-11-03', 0 UNION ALL 
    SELECT 1, DATE '2017-11-04', 1 UNION ALL 
    SELECT 1, DATE '2017-11-04', 1 UNION ALL 
    SELECT 1, DATE '2017-11-05', 0 UNION ALL 
    SELECT 2, DATE '2017-11-10', 1 UNION ALL 
    SELECT 2, DATE '2017-11-11', 0 UNION ALL 
    SELECT 2, DATE '2017-11-20', 0 UNION ALL 
    SELECT 2, DATE '2017-11-21', 1 
) 
SELECT 
    user_id, 
    date, 
    MAX(IF(event_happend = 1, date, NULL)) OVER (
    PARTITION BY user_id ORDER BY UNIX_DATE(date) 
    RANGE BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING 
) AS max_date 
FROM SampleData; 

I enthalten user_id und date, um zu sehen, was los ist. Beachten Sie, dass hier die Verwendung von RANGE wichtig ist - wenn Sie ROWS verwenden, kann es sein, dass die vorherige Zeile im Fenster den gleichen Wert date hat. Wenn Sie RANGE mit 1 PRECEDING verwenden, können Sie erzwingen, dass alle Zeilen im Fenster einen date-Wert haben, der kleiner als der aktuelle Wert ist.

Verwandte Themen