BIG QUERY SQL:使用移动参考标记滑动时间窗口上的日期

Posted

技术标签:

【中文标题】BIG QUERY SQL:使用移动参考标记滑动时间窗口上的日期【英文标题】:BIG QUERY SQL: Tagging dates on a sliding time window with a moving reference 【发布时间】:2016-07-21 06:33:01 【问题描述】:

这个帖子是干什么用的?

作为一个团队,我们希望根据以下情况将每个日期标记为 TRUE 或 FALSE;

1) visit_date 是访问者的第一次访问,然后为真

2) 对于第一次访问日期之后的所有访问日期

a) 如果 visit_date 在 LAST TRUE 的 30 天前瞻性窗口内,则与上次为 TRUE 的 visit_date(此处为 LAST TRUE)相比;然后是假的

我在使用什么数据?

包含访问者和访问日期的网站数据。

为访问者创建的每个新会话记录visit_date。我们对数据进行处理,以便每个访问者每个日期仅获取一条记录。

问题:

简单的 LAG 函数和 LEAD 函数没有帮助,因为;

1) LAST TRUE的参考位置在给定一个新的TRUE标签后不断变化

a) 对于访问者的LAST TRUE 更改,我们必须检查的记录数。下一个 TRUE 可以在 2 行或 15 行之后;这取决于访问者。

实际上,我们无法在 BigQuery 中创建一个循环

    检查visit_date是否符合条件

    如果确实如此,则将其标记为 TRUE,同时将 LAST TRUE 引用更改为此访问日期

    重复该过程直到访问者的最后一条记录

使用的查询:

First Table(table_id)只是为了得到下面的计算

访客唯一标识符

visit_date访问日期

plus_30_days 30 天 + 访问天数

lag_value上面一行的visit_date值

lead_value下一行visit_date的值

为了方便使用,所有值都转换为DAYOFYEAR()

根据上表,我使用了下面的查询

 SELECT    *
 , CASE WHEN lag_value IS NULL THEN 1 
        WHEN visit_date - lag_value > 30 THEN 1 
        WHEN lead_value IS NULL THEN 1 
        ELSE 0 END AS true_false
 FROM [project_id:dataset.table_id] 
 ORDER BY visitor, visit_date

输出:

绿色框应该是 TRUE

因为

采取的行动:

1) 我已经尝试过 LEAD 和 LAG 功能

2) 查了下,正常的可以翻译成BIGQUERY的SQL函数>>找不到循环函数

3) 询问我的团队负责人 >> 相同的问题

4) 长达 3 小时的实验 >> 相同的输出

供您参考的表格(未格式化)

visitor_id  file_date   plus_30_days    lag_value   lead_value  true_false
A   1   31  null    38  1
A   38  68  1   41  1
A   41  71  38  65  0
A   65  95  41  76  0
A   76  106 65  null    1
B   90  120 null    122 1
B   122 152 90  null    1
C   123 153 null    134 1
C   134 164 123 163 0
C   163 193 134 183 0
C   183 213 163 217 0
C   217 247 183 null    1
D   245 275 null    256 1
D   256 286 245 262 0
D   262 292 256 275 0
D   275 305 262 279 0
D   279 309 275 null    1
E   279 309 null    310 1
E   310 340 279 341 1
E   341 5   310 null    1

【问题讨论】:

【参考方案1】:

试试下面。

SELECT visitor_id, file_date, true_false FROM JS(    // input table
( SELECT visitor_id, GROUP_CONCAT(STRING(100000 + file_date), ';') AS visits FROM
    (SELECT 'A' AS visitor_id, 1 AS file_date), (SELECT 'A' AS visitor_id, 38 AS file_date), (SELECT 'A' AS visitor_id, 41 AS file_date), (SELECT 'A' AS visitor_id, 65 AS file_date),
    (SELECT 'A' AS visitor_id, 76 AS file_date), (SELECT 'B' AS visitor_id, 90 AS file_date), (SELECT 'B' AS visitor_id, 122 AS file_date), (SELECT 'C' AS visitor_id, 123 AS file_date),
    (SELECT 'C' AS visitor_id, 134 AS file_date), (SELECT 'C' AS visitor_id, 163 AS file_date), (SELECT 'C' AS visitor_id, 183 AS file_date), (SELECT 'C' AS visitor_id, 217 AS file_date),
    (SELECT 'D' AS visitor_id, 245 AS file_date), (SELECT 'D' AS visitor_id, 256 AS file_date), (SELECT 'D' AS visitor_id, 262 AS file_date), (SELECT 'D' AS visitor_id, 275 AS file_date),
    (SELECT 'D' AS visitor_id, 279 AS file_date), (SELECT 'E' AS visitor_id, 279 AS file_date), (SELECT 'E' AS visitor_id, 310 AS file_date), (SELECT 'E' AS visitor_id, 341 AS file_date)  
  GROUP BY visitor_id
) ,
// input columns
visitor_id, visits,
// output schema
"[name: 'visitor_id', type: 'string',
name: 'file_date', type: 'integer',
name: 'true_false', type: 'integer']",
// function
"function(r, emit)
  var visits = r.visits.split(';');
  visits.sort();
  plus_30_days = 0;
  for (var i = 0; i < visits.length; i++)  
    file_date = parseInt(visits[i]) - 100000;
    true_false = 0;
    if (file_date > plus_30_days) 
      plus_30_days = file_date + 30;
      true_false = 1;
    
      emit(
        visitor_id: r.visitor_id,
        file_date: file_date,
        true_false: true_false
      );      
  
 ")

希望这会给你一个好的开始 请注意:上面的示例使用了 javascript UDF 的未记录的内联版本,到目前为止,它非常适合快速演示/共享/尝试代码,但是...未记录,因此不受支持 为了在生产中使用上面的示例,您最好修改它以符合BigQuery User-Defined Functions 文档(很少有非常简单的调整)。

【讨论】:

米哈伊尔,很抱歉回复晚了。我在这里进退两难。你的回答对于我这里的数据集是正确的。但我无法为具有相同字段的 100 万行表创建相同的内容。我会投票赞成你的答案,尽管目前我无法在不测试的情况下将其标记为正确。 你到底有什么问题?超出资源?尝试对您的输入数据进行分片/分区,这样您就可以分几“批”处理您的数据 你应该按visitor_id分片 米哈伊尔,感谢您的快速回复。我无法快速回复您,因为我正在尝试了解 UDF 结构和语言。感谢您的耐心等待。 完全没问题。慢慢来。顺便说一句,检查code.google.com/p/google-bigquery/issues/detail?id=527 - 看起来很快 JS UDF 查询将能够处理 10 倍以上的内存,所以你的问题可能会消失

以上是关于BIG QUERY SQL:使用移动参考标记滑动时间窗口上的日期的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Google Big Query 中正确使用 GROUP BY 命令?

Big Query 或 SQL 重塑数据

Big Query - 使用旧版和普通 sql 时的用户数量不同

Big Query (SQL) 将多列转换为行/数组

SQL Big Query 完全连接表以使用相同的过滤器

基于会话的 Google Big Query SQL 聚合数据