You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BigQuery中LAG()函数未返回上一组会话ID问题排查

问题:BigQuery中LAG函数为何未返回预期的会话ID?

我在BigQuery中运行以下查询:

WITH mock AS (
        SELECT 
            TIMESTAMP '2024-04-01 22:26:25' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'session start' AS event_name,
            1712010385 AS ga_session_id,
            'example.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:26:28' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'view' AS event_name,
            1712010385 AS ga_session_id,
            'example.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:26:31' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'click' AS event_name,
            1712010385 AS ga_session_id,
            'example.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:26:50' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'click' AS event_name,
            1712010385 AS ga_session_id,
            'example.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:27:02' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'session start' AS event_name,
            2939469694 AS ga_session_id,
            'example2.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:27:14' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'view' AS event_name,
            2939469694 AS ga_session_id,
            'example2.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:27:50' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'click' AS event_name,
            2939469694 AS ga_session_id,
            'example2.com' AS hostname
    ),
    
    raw AS (
        SELECT 
            event_timestamp,
            user_pseudo_id,
            event_name,
            hostname,
            ga_session_id,
            MIN(event_timestamp) OVER (PARTITION BY user_pseudo_id, ga_session_id) AS session_start
        FROM mock
    )
    
    SELECT 
        *, 
        LAG(ga_session_id) OVER (PARTITION BY user_pseudo_id ORDER BY session_start) AS ga_session_id_fix
    FROM raw
    ORDER BY event_timestamp ASC;

得到如下输出:

Rowevent_timestampuser_pseudo_idevent_namehostnamega_session_idsession_startga_session_id_fix
12024-04-01 22:26:25 UTCh6p2ylt679me5pczsession startexample.com17120103852024-04-01 22:26:25 UTCnull
22024-04-01 22:26:28 UTCh6p2ylt679me5pczviewexample.com17120103852024-04-01 22:26:25 UTC1712010385
32024-04-01 22:26:31 UTCh6p2ylt679me5pczclickexample.com17120103852024-04-01 22:26:25 UTC1712010385
42024-04-01 22:26:50 UTCh6p2ylt679me5pczclickexample.com17120103852024-04-01 22:26:25 UTC1712010385
52024-04-01 22:27:02 UTCh6p2ylt679me5pczsession startexample2.com29394696942024-04-01 22:27:02 UTC1712010385
62024-04-01 22:27:14 UTCh6p2ylt679me5pczviewexample2.com29394696942024-04-01 22:27:02 UTC2939469694
72024-04-01 22:27:50 UTCh6p2ylt679me5pczclickexample2.com29394696942024-04-01 22:27:02 UTC2939469694

为何最后两行的ga_session_id_fix列未返回第一个会话的ID?


原因分析

当前查询中使用的LAG(ga_session_id) OVER (PARTITION BY user_pseudo_id ORDER BY session_start)是逐行取上一行的ga_session_id值,而非按会话分组取上一个会话的ID:

  • 第5行属于第二个会话的第一行,它的上一行是第一个会话的最后一行(第4行),所以返回第一个会话的ID;
  • 第6行的上一行是第5行(同属第二个会话),所以返回当前会话的ID;
  • 第7行同理,上一行是第6行,返回当前会话的ID。

如果需求是让同一个会话的所有行都关联前一个会话的ID,需要先按会话维度计算前一个会话ID,再关联回原始事件数据。


修正后的查询

WITH mock AS (
        SELECT 
            TIMESTAMP '2024-04-01 22:26:25' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'session start' AS event_name,
            1712010385 AS ga_session_id,
            'example.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:26:28' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'view' AS event_name,
            1712010385 AS ga_session_id,
            'example.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:26:31' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'click' AS event_name,
            1712010385 AS ga_session_id,
            'example.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:26:50' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'click' AS event_name,
            1712010385 AS ga_session_id,
            'example.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:27:02' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'session start' AS event_name,
            2939469694 AS ga_session_id,
            'example2.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:27:14' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'view' AS event_name,
            2939469694 AS ga_session_id,
            'example2.com' AS hostname
        UNION ALL
        SELECT 
            TIMESTAMP '2024-04-01 22:27:50' AS event_timestamp,
            'h6p2ylt679me5pcz' AS user_pseudo_id,
            'click' AS event_name,
            2939469694 AS ga_session_id,
            'example2.com' AS hostname
    ),
    
    raw AS (
        SELECT 
            event_timestamp,
            user_pseudo_id,
            event_name,
            hostname,
            ga_session_id,
            MIN(event_timestamp) OVER (PARTITION BY user_pseudo_id, ga_session_id) AS session_start
        FROM mock
    ),
    
    session_level AS (
        SELECT 
            user_pseudo_id,
            ga_session_id,
            session_start,
            LAG(ga_session_id) OVER (PARTITION BY user_pseudo_id ORDER BY session_start) AS prev_session_id
        FROM raw
        GROUP BY user_pseudo_id, ga_session_id, session_start
    )
    
    SELECT 
        r.*,
        s.prev_session_id AS ga_session_id_fix
    FROM raw r
    LEFT JOIN session_level s 
        ON r.user_pseudo_id = s.user_pseudo_id 
        AND r.ga_session_id = s.ga_session_id
    ORDER BY r.event_timestamp ASC;

修正后的输出

Rowevent_timestampuser_pseudo_idevent_namehostnamega_session_idsession_startga_session_id_fix
12024-04-01 22:26:25 UTCh6p2ylt679me5pczsession startexample.com17120103852024-04-01 22:26:25 UTCnull
22024-04-01 22:26:28 UTCh6p2ylt679me5pczviewexample.com17120103852024-04-01 22:26:25 UTCnull
32024-04-01 22:26:31 UTCh6p2ylt679me5pczclickexample.com17120103852024-04-01 22:26:25 UTCnull
42024-04-01 22:26:50 UTCh6p2ylt679me5pczclickexample.com17120103852024-04-01 22:26:25 UTCnull
52024-04-01 22:27:02 UTCh6p2ylt679me5pczsession startexample2.com29394696942024-04-01 22:27:02 UTC1712010385
62024-04-01 22:27:14 UTCh6p2ylt679me5pczviewexample2.com29394696942024-04-01 22:27:02 UTC1712010385
72024-04-01 22:27:50 UTCh6p2ylt679me5pczclickexample2.com29394696942024-04-01 22:27:02 UTC1712010385

内容的提问来源于stack exchange,提问作者Simon Breton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 07:14:54