如何在BigQuery中扩展透视?

Mik*_*ant 5 sql google-bigquery

比方说,我有一个给定的一天音乐视频播放统计数据表格mydataset.stats(3B行,1M用户,6K艺术家).简化的架构是:UserGUID String,ArtistGUID String

我需要从行列枢轴/转的艺术家,这样的模式将是:
UserGUID字符串,Artist1诠释,Artist2诠释,... Artist8000诠释
与艺术家通过各自的用户播放次数

如何将行转换为具有BigQuery/SQL中大量数据的列中的方法中提出了一种方法以及如何在Google BigQuery中为数千个类别创建虚拟变量列?但看起来它不能扩展我的例子中的数字

我的例子可以缩放这种方法吗?

Mik*_*ant 8

我尝试了下面的方法,最多6000个功能,它按预期工作.我相信它最多可以使用10K功能,这是表格中列数的硬限制

第1步 - 按用户/艺术家汇总播放

SELECT userGUID as uid, artistGUID as aid, COUNT(1) as plays 
FROM [mydataset.stats] GROUP BY 1, 2
Run Code Online (Sandbox Code Playgroud)

第2步 - 规范化uid和辅助 - 因此它们是连续的数字1,2,3,....
我们至少有两个原因需要这个:a)以后动态创建的sql尽可能紧凑,b)有更多可用/友好的列名

结合第一步 - 它将是:

SELECT u.uid AS uid, a.aid AS aid, plays 
FROM (
  SELECT userGUID, artistGUID, COUNT(1) AS plays 
  FROM [mydataset.stats] 
  GROUP BY 1, 2
) AS s
JOIN (
  SELECT userGUID, ROW_NUMBER() OVER() AS uid FROM [mydataset.stats] GROUP BY 1
) AS u ON u. userGUID = s.userGUID
JOIN (
  SELECT artistGUID, ROW_NUMBER() OVER() AS aid FROM [mydataset.stats] GROUP BY 1
) AS a ON a.artistGUID = s.artistGUID 
Run Code Online (Sandbox Code Playgroud)

让我们将输出写入表 - mydataset.aggs

第3步 - 一次使用已建议(在上述问题中)N个特征(艺术家)的方法.在我的特定示例中,通过实验,我发现基本方法适用于2000到3000之间的功能数量.为了安全起见,我决定一次使用2000个功能

下面的脚本用于动态生成查询,然后运行以创建分区表

SELECT 'SELECT uid,' + 
   GROUP_CONCAT_UNQUOTED(
      'SUM(IF(aid=' + STRING(aid) + ',plays,NULL)) as a' + STRING(aid) 
   ) 
   + ' FROM [mydataset.aggs] GROUP EACH BY uid'
FROM (SELECT aid FROM [mydataset.aggs] GROUP BY aid HAVING aid > 0 and aid < 2001)
Run Code Online (Sandbox Code Playgroud)

上面的查询产生另一个查询,如下所示:

SELECT uid,SUM(IF(aid=1,plays,NULL)) a1,SUM(IF(aid=3,plays,NULL)) a3,
  SUM(IF(aid=2,plays,NULL)) a2,SUM(IF(aid=4,plays,NULL)) a4 . . .
FROM [mydataset.aggs] GROUP EACH BY uid 
Run Code Online (Sandbox Code Playgroud)

这应该运行和写入 mydataset.pivot_1_2000

执行STEP 3两次(调整HAVING aid > NNNN and aid < NNNN)我们得到另外三个表mydataset.pivot_2001_4000,mydataset.pivot_4001_6000
正如您所看到的 - mydataset.pivot_1_2000具有预期的模式,但是对于从1到2001的辅助功能; mydataset.pivot_2001_4000只有2001年至4000年的援助功能; 等等

步骤4 - 将所有分区数据透视表合并到最终数据透视表,所有功能在一个表中表示为列

与上述步骤相同.首先我们需要生成查询然后运行它所以,最初我们将"缝合"mydataset.pivot_1_2000和mydataset.pivot_2001_4000.然后使用mydataset.pivot_4001_6000得到结果

SELECT 'SELECT x.uid uid,' + 
   GROUP_CONCAT_UNQUOTED(
      'a' + STRING(aid) 
   ) 
   + ' FROM [mydataset.pivot_1_2000] AS x
JOIN EACH [mydataset.pivot_2001_4000] AS y ON y.uid = x.uid
'
FROM (SELECT aid FROM [mydataset.aggs] GROUP BY aid HAVING aid < 4001 ORDER BY aid)
Run Code Online (Sandbox Code Playgroud)

应运行上面的输出字符串并将结果写入 mydataset.pivot_1_4000

然后我们重复步骤4,如下所示

SELECT 'SELECT x.uid uid,' + 
   GROUP_CONCAT_UNQUOTED(
      'a' + STRING(aid) 
   ) 
   + ' FROM [mydataset.pivot_1_4000] AS x
JOIN EACH [mydataset.pivot_4001_6000] AS y ON y.uid = x.uid
'
FROM (SELECT aid FROM [mydataset.aggs] GROUP BY aid HAVING aid < 6001 ORDER BY aid)
Run Code Online (Sandbox Code Playgroud)

要写入的结果 mydataset.pivot_1_6000

结果表具有以下模式:

uid int, a1 int, a2 int, a3 int, . . . , a5999 int, a6000 int 
Run Code Online (Sandbox Code Playgroud)

注意:
a.我尝试了这种方法,最多只有6000个功能,它按预期工作
b.步骤3和4中第二次/主要查询的运行时间从20到60分钟
不等.重要提示:步骤3和4中的计费层从1到90不等.好消息是各个表的大小相对较小(30-40MB),因此计费字节也是如此.对于"2016年之前"项目,所有项目都被计为第1级,但在2016年10月之后,这可能是一个问题.
欲了解更多信息,请参见Timing高计算查询
d.以上示例显示了使用BigQuery进行大规模数据转换的强大功能!我认为(但我可能错了)存储物化特征矩阵不是最好的主意