BigQuery 计算值多列之间的重叠百分比
BigQuery Calculating Percent Overlap Between Values Multiple Columns
我对 SQL 和 bigquery 还很陌生,正在处理大约 140 万行的数据集。
我目前感兴趣的值是category_name(字符串),item_id(字符串)。我感兴趣的是计算 category_name 中每个值的不同 item_id(此列总共有 269 个不同值)。基本上在我的基础数据集中,每一行数据都包含一个 item_id 的实例,它显示在一个 category_name 中,其中 item_id 可以根据数量每天有多行那天出现了 category_name 秒。
我已经能够 运行 一个成功的查询,为 category_name 的每个值添加不同的 item_id 的新列,现在最终输出应该是什么我不知道如何计算 1 category_name 的不同 item_id 的百分比也出现在所有其他 category_name 中。所以基本上我正在寻找一个新列(如枢轴 table),它将计算匹配的 item_ids 2 category_names,然后将该计数除以总的不同 item_id 在 1 category_name 中。因此,基本上每个 category_name 将有 269 个新列,每一行将代表基础 category_name 与其他每个 category_name 的重叠百分比。
这是我的 table 目前我感兴趣的数据
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_name 进行比较,并找到 matches/total distinct_items 基于 item_ids。如果有另一种方法可以在没有枢轴 table 的情况下获得此输出,那也将不胜感激。上下文有 269 个 category_name 和 6525 个不同的 item_id。
如果有一个更简单的公式,我可以在 google Data Studio 中使用此聚合,因为 Data Studio 中的最终输出应该是散点图,其中 x 和 y 轴 category_names 和气泡是 % 重叠,所以基本上只是用散点图可视化枢轴 table 结果。如果我的描述和问题中的任何内容没有意义或需要更清楚地说明,请随时标记我并让我知道什么是令人困惑的。任何帮助是极大的赞赏!谢谢
您可以使用条件聚合:
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;
以下适用于 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:在您的简化示例中,我主要处理数据。在您的实际情况下,您可能需要进行一些小的调整 - 如果您对此有任何疑问 - 请 post 新问题
我对 SQL 和 bigquery 还很陌生,正在处理大约 140 万行的数据集。
我目前感兴趣的值是category_name(字符串),item_id(字符串)。我感兴趣的是计算 category_name 中每个值的不同 item_id(此列总共有 269 个不同值)。基本上在我的基础数据集中,每一行数据都包含一个 item_id 的实例,它显示在一个 category_name 中,其中 item_id 可以根据数量每天有多行那天出现了 category_name 秒。
我已经能够 运行 一个成功的查询,为 category_name 的每个值添加不同的 item_id 的新列,现在最终输出应该是什么我不知道如何计算 1 category_name 的不同 item_id 的百分比也出现在所有其他 category_name 中。所以基本上我正在寻找一个新列(如枢轴 table),它将计算匹配的 item_ids 2 category_names,然后将该计数除以总的不同 item_id 在 1 category_name 中。因此,基本上每个 category_name 将有 269 个新列,每一行将代表基础 category_name 与其他每个 category_name 的重叠百分比。
这是我的 table 目前我感兴趣的数据
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_name 进行比较,并找到 matches/total distinct_items 基于 item_ids。如果有另一种方法可以在没有枢轴 table 的情况下获得此输出,那也将不胜感激。上下文有 269 个 category_name 和 6525 个不同的 item_id。
如果有一个更简单的公式,我可以在 google Data Studio 中使用此聚合,因为 Data Studio 中的最终输出应该是散点图,其中 x 和 y 轴 category_names 和气泡是 % 重叠,所以基本上只是用散点图可视化枢轴 table 结果。如果我的描述和问题中的任何内容没有意义或需要更清楚地说明,请随时标记我并让我知道什么是令人困惑的。任何帮助是极大的赞赏!谢谢
您可以使用条件聚合:
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;
以下适用于 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:在您的简化示例中,我主要处理数据。在您的实际情况下,您可能需要进行一些小的调整 - 如果您对此有任何疑问 - 请 post 新问题