如何优化 google-bigquery 以从大数据表中查找最常见的类别?

Posted

技术标签:

【中文标题】如何优化 google-bigquery 以从大数据表中查找最常见的类别?【英文标题】:how to optimize google-bigquery for finding most frequent categories from big data table? 【发布时间】:2019-04-21 00:37:00 【问题描述】:

我在芝加哥犯罪数据集上使用 google-bigquery。但是,我想从primary_type 列中找出每个不同的block 最常见的犯罪类型。为此,我关注standardSQL

数据:

由于芝加哥犯罪数据比较大,有官网可以预览数据集:crime data on Google cloud

我目前的标准 SQL:

SELECT primary_type,block, COUNT(*) as count
FROM `bigquery-public-data.chicago_crime.crime` 
HAVING COUNT(*) = (SELECT MAX(count)
  FROM (SELECT primary_type, COUNT(*) as count FROM `bigquery-public-data.chicago_crime.crime` GROUP BY primary_type, block) `bigquery-public-data.chicago_crime.crime`)

我上面的查询的问题是它现在有一个错误,对我来说,这个查询效率很低,即使我修复了错误。如何修复和优化上述查询?

如何在标准 SQL 中使用正则表达式:

要计算每个区块最常见的类型,包括南北,我必须处理regex,例如033XX S WOOD ST,我应该只得到S WOOT ST033XX N WOOD ST。我需要得到N WOOD ST 并计算这些。我该怎么做?

想要的输出:

在我想要的输出中,对于每个块,例如 WOOD ST (North (N WOOD ST)South(S WOOD ST))。我想找到最常见的犯罪类型。在我的最终输出中,我期待三列,例如blockprimary_typecount。有什么办法可以通过google-bigquery 完成这项工作?

【问题讨论】:

【参考方案1】:

以下是 BigQuery 标准 SQL

#standardSQL
SELECT
  block,
  ARRAY_AGG(STRUCT(primary_type, cnt) ORDER BY cnt DESC LIMIT 1)[OFFSET(0)].*
FROM (
  SELECT 
    block,
    primary_type, 
    COUNT(*) cnt
  FROM `bigquery-public-data.chicago_crime.crime` 
  GROUP BY block, primary_type
)
GROUP BY block   

我怎样才能获得街区 WOOD ST 上最常见的犯罪类型?有什么技巧可以做到这一点吗?

我不熟悉这些数据的具体细节,但从简要一瞥 - 我认为您可以在下面尝试

#standardSQL
SELECT
  block,
  ARRAY_AGG(STRUCT(primary_type, cnt) ORDER BY cnt DESC LIMIT 1)[OFFSET(0)].*
FROM (
  SELECT 
    SUBSTR(block, 8) block,
    primary_type, 
    COUNT(*) cnt
  FROM `bigquery-public-data.chicago_crime.crime` 
  GROUP BY block, primary_type
)
GROUP BY block

【讨论】:

你能给我几行解释你的查询吗?我想了解您的解决方案。谢谢。 当然。内部 SELECT 只是简单地计算每个块和类别的计数。然后,外部 SELECT 只为每个块选择最常见的类别! 我只是想了解您查询的语法,为什么要使用 ARRAY_AGG()[OFFSET(0)].* FROM() ?为什么在这里使用.* 操作? 尝试删除.*,你会看到不同:o) 它类似于使用SELECT * FROM table 从给定表中选择所有列 - 这里相同 - 它从 STRUCT 中选择所有字段。很高兴它有帮助:o)【参考方案2】:

这应该为您提供最常见的犯罪率

内部查询计数计算犯罪频率,窗口划分函数根据块划分的犯罪频率降序计算排名。外部查询 where 子句 rank =1 只返回最常见的犯罪。您可以更改外部查询 where 子句,通过使其排名 来获得前 5 名常见犯罪


select * from 
      (SELECT block, primary_type, count(primary_type) as crime_frquency, 
            ROW_NUMBER() OVER (PARTITION BY block ORDER BY count(primary_type) DESC) AS rank
       FROM  `bigquery-public-data.chicago_crime.crime` 
       group by block, primary_type)
where rank = 1


【讨论】:

以上是关于如何优化 google-bigquery 以从大数据表中查找最常见的类别?的主要内容,如果未能解决你的问题,请参考以下文章

如何同步调用 google-bigquery 删除和插入 API?

如何在没有授权令牌的情况下从 python 脚本查询 google-bigquery 中的私有表?

如何优化大数据字符串的串行通信?

如何在Python中优化计算大数

优化查询以从不同的表中获取唯一(用户)记录

Google-Bigquery:整合聚合