我想在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中创建变量或使用循环...)
答案 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个子选择(可以用更短的形式编写,但它不会改变性能)。说明:
有关详细信息,请参阅以下文档: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
});
}"
)