如何在 BQ 中的数组字段上做相当于“不同”的操作?

Posted

技术标签:

【中文标题】如何在 BQ 中的数组字段上做相当于“不同”的操作?【英文标题】:How to do the equivalent of 'distinct' on array field in BQ? 【发布时间】:2021-06-14 01:53:32 【问题描述】:

让我们获取以下数据:

也可以在BQ中用如下语句生成:

with x as (
    select 1 as RowID, DATE('2014-01-01') as Date, [200, 300] as Payments, ["Contractor", "Monday"] as Tags union all
    select 2 as RowID, DATE('2014-01-02') as Date, [100, 200, 200, 200, 700] as Payments, ["Contractor", "Bi-Weekly"] as Tags
)
select * from x

我将如何在以下右侧进行以下两个“不同”总计:

也就是说,我想得到一个不会重复计算的“总数”,或者更确切地说,只获取基于 RowID 的不同项目。

【问题讨论】:

【参考方案1】:

如果我理解正确,那是您真正关心的总行数。您可以通过并行取消标签和付款来计算前两列。

然后对于总额,取消不带标签的付款:

with x as (
      select 1 as RowID, DATE('2014-01-01') as Date, [200, 300] as Payments, ["Contractor", "Monday"] as Tags union all
      select 2 as RowID, DATE('2014-01-02') as Date, [100, 200, 200, 200, 700] as Payments, ["Contractor", "Bi-Weekly"] as Tags
     )
select tag, count(*), sum(payment)
from x cross join
     unnest(x.payments) payment cross join
     unnest(x.tags) tag
group by 1
union all 
select 'Total', count(*), sum(payment)
from x cross join
      unnest(x.payments) payment;

【讨论】:

漂亮,正是我想要的。以上是查询数组的常用方法吗?我总是争论正确的方法是“双重计算”还是进行总计以获得原始数据集的实际计数/总数。有没有更“正确”的方法来做到这一点? @David542。 . .这将获得您想要的计数。我认为没有比这更简单的方法了。 对,我的意思是这是用数组做双向相关事情的常用方法吗?还是经常重复计算? 我想一个更好的提问方式是,如果您要查看付款的“总计”,您希望看到$1900$3800?还是更多地取决于具体情况,并且在不同的时间可能更可取? I don't think there is a simpler method than this. - 我认为我的回答提出了更简单的方法:o)【参考方案2】:

考虑下面

select tag, sum(payment) amount_paid, count(payment) payments_count 
from data, unnest(tags || ['Total']) tag, unnest(payments) payment
group by tag

如果应用于您问题中的样本数据 - 输出是

【讨论】:

太棒了!添加order by (tag='total'),以便阅读底部的总计。 您是否见过有人希望总数为3800 而不是您在与任何客户合作时所拥有的?或者如果有人曾经使用过数组,1900 是“正确”的答案吗? 根据我的经验 - 预计总数为 1900。从未见过预期 3800 的实际案例

以上是关于如何在 BQ 中的数组字段上做相当于“不同”的操作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在sqlite中的两个字段上做group_concat?

mysql 表操作

Bigquery 自动转换数据中的字段

如何将 spark scala map 字段合并到 BQ?

CSV 到 BQ:空字段而不是空值

Mysql:表操作