在BigQuery中创建页面路径表(路径分析; Unpivot)

时间:2016-05-06 12:38:39

标签: sql google-bigquery

我想在BigQuery中重新创建一个用于路径分析的表(类似于unpivot)。 对于每个人,我都有他/她的页面路径数据,如下所示。

[visitor]   [page]     [page_orders]  
A,  Pa, 1
A,  Pb, 2
A,  Pc, 3
A,  Pb, 4
A,  Pf, 5
B,  Px, 1
B,  Pb, 2
B,  Pz, 3
B,  Pk, 4
C,  Pb, 1
C,  Pz, 2
C,  Pa, 3

我想创建这样的表格。

[visitor]       [page_path]
A,  Pz > Pb > Pc > Pa > Pf
B,  Px > Pb > Pz > Pk 
C,  Pb > Pz > Pa 

我所做的是创建一个这样的表:

[visitor] [Pa] [Pb] [Pc] [Pf] [Pk] [Px] [Pz]
A, 0, 0, 0, 0, 0, 0, 1
A, 0, 1, 0, 0, 0, 0, 0
A, 0, 0, 1, 0, 0, 0, 0
A, 1, 0, 0, 0, 0, 0, 0
A, 0, 0, 0, 1, 0, 0, 0
B, 0, 0, 0, 0, 0, 1, 0
B, 0, 1, 0, 0, 0, 0, 0
B, 0, 0, 0, 0, 0, 0, 1
B, 0, 0, 0, 0, 1, 0, 0 
C, 0, 1, 0, 0, 0, 0, 0
C, 0, 0, 0, 0, 0, 0, 1
C, 1, 0, 0, 0, 0, 0, 0

然后我可以得到一张这样的表

A, Pa Pb Pc Pf Pz
B, Pb Pk Px Pz
C, Pa Pb Pz

但是,页面顺序不正确。

有没有更好的想法通过BigQuery创建正确的页面路径表? (似乎我无法在BigQuery中创建变量或使用循环...)

3 个答案:

答案 0 :(得分:1)

通过BigQuery对标准SQL的支持,可以通过在ARRAY上使用本机操作来解决这个问题。 以下是一种可能的解决方案:

select visitor, (select string_agg(p, ' --> ') from t.pages p) from
(select visitor, array(select p.page from t.pages p order by p.page_order asc) pages from
(select visitor, array_agg(struct(page, page_order)) pages
 from VisitsTable group by visitor) t) t

为了清晰起见,解决方案被写为3个子选择(可以用更短的形式编写,但它不会改变性能)。说明:

  1. 最内层的ARRAY_AGG聚合为每个访问者构建一个ARRAY STRUCT。每个STRUCT都有STRING页面和INT64 page_order。
  2. 第二个子选择在每个数组中运行ORDER BY 。它按订单排序页面。
  3. 最外面的subselect只计算每个ARRAY中所有字符串的STRING_AGG,使用' - > '作为分隔符。
  4. 有关详细信息,请参阅以下文档:https://cloud.google.com/bigquery/sql-reference/

答案 1 :(得分:0)

您可以对原始数据使用条件聚合:

select visitor,
       concat(max(case when page_order = 1 then page else '' end), 
              max(case when page_order = 2 then concat(' --> ', page) else '' end),
              max(case when page_order = 3 then concat(' --> ', page)  else '' end), 
              max(case when page_order = 4 then concat(' --> ', page)  else '' end), 
              max(case when page_order = 5 then concat(' --> ', page)  else '' end),
              max(case when page_order = 6 then concat(' --> ', page)  else '' end),
              max(case when page_order = 7 then concat(' --> ', page)  else '' end)
 ) as path
             )
from t
group by visitor;

答案 2 :(得分:0)

SELECT visitor, GROUP_CONCAT(page, ' > ') as page_path
FROM (
  SELECT visitor, page, page_order 
  FROM YourTable
  ORDER BY visitor, page_order
)
GROUP BY visitor

另一种选择:使用BigQuery User-Defined Functions(不依赖于Mosha在他的评论中指出的顺序 - 但UDF有其自身的局限性 - 所以你需要选择)

SELECT visitor, page_path FROM JS(
// input table
(
  SELECT visitor, GROUP_CONCAT(CONCAT(STRING(100000 + page_order), ',', page), ';') AS list
  FROM YourTable
  GROUP BY visitor
) ,
// input columns
visitor, list,
// output schema
"[
{name: 'visitor', type: 'string'},
{name: 'page_path', type: 'string'}
]",
// function
"function(r, emit){
  var list = r.list.split(';');
  list.sort();
  path = ''
  for (var i = 0; i < list.length; i++) {
    if (i > 0) path += ' > ';
    path += list[i].split(',')[1];
  }
    emit({
      visitor: r.visitor,
      page_path: path
    });
 }"
)