Запрос с условным оператором задержки - PullRequest
0 голосов
/ 22 ноября 2018

Я пытаюсь найти предыдущее значение столбца, где строка соответствует некоторым критериям.Рассмотрим таблицу:

| user_id | session_id | time       | referrer   |  
|---------|------------|------------|------------|  
| 1       | 1          | 2018-01-01 | [NULL]     |  
| 1       | 2          | 2018-02-01 | google.com |  
| 1       | 3          | 2018-03-01 | google.com |

Я хочу найти для каждого сеанса предыдущее значение session_id, где реферер равен NULL.Таким образом, для второй И третьей строки значение parent_session_id должно быть 1.

Однако, просто используя lag(session_id) over (partition by user_id order by time), я получу parent_session_id = 2 для 3-й строки.

Я подозреваю, что это можно сделать с помощью комбинации оконных функций, но я просто не могу понять это.

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Я бы использовал last_value () в сочетании с if ():

WITH t AS (SELECT * FROM UNNEST([ 
    struct<user_id int64, session_id int64, time date, referrer string>(1, 1, date('2018-01-01'), NULL),
    (1,2,date('2018-02-01'), 'google.com'),
    (1,3,date('2018-03-01'), 'google.com')
  ]) )

SELECT
  *,
  last_value(IF(referrer is null, session_id, NULL) ignore nulls) 
    over (partition by user_id order by time rows between unbounded preceding and 1 preceding) lastNullrefSession
FROM t
0 голосов
/ 22 ноября 2018

Вы можете даже сделать это с помощью коррелированного подзапроса:

SELECT
    session_id,
    (SELECT MAX(t2.session_id) FROM yourTable t2
     WHERE t2.referrer IS NULL AND t2.session_id < t1.session_id) prev_session_id
FROM yourTable t1
ORDER BY
    session_id;

Вот подход, использующий аналитические функции, которые могут работать:

WITH cte AS (
    SELECT *,
        SUM(CASE WHEN referrer IS NULL THEN 1 ELSE 0 END)
            OVER (ORDER BY session_id) cnt
    FROM yourTable
)

SELECT
    session_id,
    CASE WHEN cnt = 0
         THEN NULL
         ELSE MIN(session_id) OVER (PARTITION BY cnt) END prev_session_id
FROM cte
ORDER BY
    session_id;
...