BigQuery计算值在多列之间的重叠百分比

问题描述 投票:0回答:2

我对SQL和bigquery还是相当陌生,并且正在使用约140万行的数据集。

我当前感兴趣的值是category_name(字符串),item_id(字符串)。我感兴趣的是为category_name中的每个值计算不同的item_id(此列共有269个不同的值)。基本上在我的基本数据集中,每一行数据都包含一个item_id的实例,该实例以单个category_name出现,其中item_id可以根据当天出现的category_name的数量每天有多行。

我已经能够运行成功的查询,为category_name的每个值添加一个新列,用于显示不同item_id的值,现在最终输出应该是我不知道该怎么做的是为以下内容计算不同item_ids的百分比: 1个类别名称,也出现在其他所有类别名称中。因此,基本上,我正在寻找一个新列(如数据透视表),该列将对2个category_names的匹配item_ids进行计数,然后将该计数除以1 category_name中不同的item_id总数。因此,每个category_name本质上将有269个新列,并且每一行将代表基本category_name与其他category_name的重叠百分比。

[这是我当前感兴趣的表中的数据

category_name  |   item_id
---------------|------------
category1      |  item1
category2      |  item1
category3      |  item1
category1      |  item2
category4      |  item2
category1      |  item3
category5      |  item3
category5      |  item2
category6      |  item4
category3      |  item5
category3      |  item6
category1      |  item6
category2      |  item5
category1      |  item4

这是我当前的查询结果如下

category_name  |  distinct_items
---------------|-----------------
category1      |  5
category2      |  2
category3      |  3
category4      |  1
category5      |  2
category6      |  1

这是我希望最终输出看起来像的样子:

category_name  | category1   |  category2  |   category3   |   category4   |  category5  |  category6
--------------------------------------------------------------------------------------------------------
category1      |   100%      |     20%     |      40%      |      20%      |     40%     |     20%
category2      |    50%      |     100%    |      100%     |       0%      |      0%     |     0%
category3      |    66.67%   |     66.67%  |      100%     |       0%      |      0%     |     0%
category4      |   100%      |      0%     |       0%      |      100%     |     100%    |     0%
category5      |   100%      |      0%     |       0%      |       50%     |     100%    |     0%
category6      |   100%      |      0%     |       0%      |       0%      |      0%     |    100%

基本上,category_name的行值将是该category_name作为目标,并将它们的总distinct_items与其他category_names进行比较,并根据item_ids查找匹配项/总distinct_items的百分比。如果有另一种无需枢轴表来获得此输出的方法,也将不胜感激。上下文有269个category_names和6525个不同的item_ids。

[如果有一个更简单的公式,我可以在google data studio中使用此汇总,因为它在data studio中的最终输出应该是带有x和y轴的散点图,category_names和气泡为%重叠,所以也可以正常工作只需使用散点图可视化数据透视表结果即可。如果我的描述和问题中的任何内容没有意义或需要进一步说明,请随时为我添加标签,并让我知道造成混淆的地方。任何帮助是极大的赞赏!谢谢

sql google-bigquery pivot-table google-data-studio
2个回答
0
投票

您可以使用条件聚合:

select t.category_name,
       countif( t2.category_name = 'category1' ) / count(*) as category1,
       countif( t2.category_name = 'category2' ) / count(*) as category2,
       countif( t2.category_name = 'category3' ) / count(*) as category3,
       countif( t2.category_name = 'category4' ) / count(*) as category4,
       countif( t2.category_name = 'category5' ) / count(*) as category5
from t join
     t t2
     on t.item = t2.item
group by t.category_name;

如果将值放在行而不是列中,这会更简单:

select t.category_name, t2.category_name,
       count(*) / sum(count(*)) over (partition by t.category_name) as ratio
from t join
     t t2
     on t.item = t2.item
group by t.category_name, t2.category_name;

0
投票

下面是BigQuery标准SQL的内容>>

步骤1

-动态生成查询文本,因此您无需手动输入所有269个类别...
#standardSQL
SELECT '''SELECT category_name, ''' || 
  STRING_AGG(DISTINCT
    ' MAX(IF(category_name2 = "' || category_name || '", percent, NULL)) AS ' || category_name
  ) || '''
FROM (
  SELECT t1.category_name, t2.category_name category_name2,
    ROUND(100 * COUNTIF(t1.item_id = t2.item_id) / COUNT(DISTINCT t1.item_id), 2) percent
  FROM `project.dataset.table` t1 
  CROSS JOIN `project.dataset.table` t2
  GROUP BY t1.category_name, t2.category_name
)
GROUP BY category_name
'''
FROM `project.dataset.table`

如果您针对问题中的示例数据在上方运行-您将获得以下查询的拼合版本

SELECT category_name, 
  MAX(IF(category_name2 = "category1", percent, NULL)) AS category1, 
  MAX(IF(category_name2 = "category2", percent, NULL)) AS category2, 
  MAX(IF(category_name2 = "category3", percent, NULL)) AS category3, 
  MAX(IF(category_name2 = "category4", percent, NULL)) AS category4, 
  MAX(IF(category_name2 = "category5", percent, NULL)) AS category5, 
  MAX(IF(category_name2 = "category6", percent, NULL)) AS category6 
FROM ( 
  SELECT t1.category_name, t2.category_name category_name2, 
  ROUND(100 * COUNTIF(t1.item_id = t2.item_id) / COUNT(DISTINCT t1.item_id), 2) percent 
  FROM `project.dataset.table` t1 
  CROSS JOIN `project.dataset.table` t2 
  GROUP BY t1.category_name, t2.category_name 
) 
GROUP BY category_name   

[步骤2

-复制步骤1中的查询结果,然后将其作为查询运行-就这样!

如果您将其应用于问题中的样本数据,则输出为

Row category_name   category1   category2   category3   category4   category5   category6    
1   category1       100.0       20.0        40.0        20.0        40.0        20.0     
2   category2       50.0        100.0       100.0       0.0         0.0         0.0  
3   category3       66.67       66.67       100.0       0.0         0.0         0.0  
4   category4       100.0       0.0         0.0         100.0       100.0       0.0  
5   category5       100.0       0.0         0.0         50.0        100.0       0.0  
6   category6       100.0       0.0         0.0         0.0         0.0         100.0         

注意1:您可以使用任何选择的客户端来自动化上述整个过程注意2:在您的简化示例中,我大部分都是根据数据来计算的。在实际情况下,您可能需要进行一些细微调整-如果对此有任何疑问-请发布新问题

© www.soinside.com 2019 - 2024. All rights reserved.