在 bigquery 中使用 RANGE_BUCKET 时如何显示存储桶名称

Posted

技术标签:

【中文标题】在 bigquery 中使用 RANGE_BUCKET 时如何显示存储桶名称【英文标题】:How to show the bucket name when using RANGE_BUCKET in bigquery 【发布时间】:2020-05-30 19:27:40 【问题描述】:

这是我在 BigQuery 中对公共数据集的查询:

SELECT RANGE_BUCKET(reputation, [400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000]) AS reputation_group, COUNT(*) AS count
FROM `bigquery-public-data.***.users`
Where reputation > 200000
GROUP BY 1
ORDER By 1

结果如下:

我怎样才能显示存储桶的范围,而不是将reputation_group显示为整数:

0: [0-400000]
1: [400001-500000]
2: [500001-600000]
....

非常感谢。

更新: 非常感谢米哈伊尔的回答,下面有一个小的改动:

SELECT bucket, 
  FORMAT('%i - %i', IFNULL(ranges[SAFE_OFFSET(bucket - 1)] + 1, 0), ranges[SAFE_OFFSET(bucket)]) AS reputation_group, 
  COUNT(*) AS COUNT
FROM `bigquery-public-data.***.users`,
UNNEST([STRUCT([200000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000] AS ranges)]),
UNNEST([RANGE_BUCKET(reputation, ranges)]) bucket 
WHERE reputation > 200000
GROUP BY 1, 2
ORDER BY bucket 

注意额外的项目 200000 被添加到 STRUCT 中,这使得结果显示 200001 - 400000 而不是 0 - 400000

【问题讨论】:

【参考方案1】:

带有JOIN 和一些重构:

WITH range_array AS (
  SELECT [400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000]
)
, buckets AS (
  SELECT LAG(bucket_end) OVER(ORDER BY reputation_group) bucket_start, *
  FROM UNNEST((SELECT * FROM range_array)) bucket_end WITH OFFSET reputation_group
)

SELECT *
  , (SELECT AS STRUCT * FROM buckets WHERE a.reputation_group = reputation_group) bucket
FROM (
  SELECT RANGE_BUCKET(reputation, (SELECT * FROM range_array)) AS reputation_group, COUNT(*) AS count
  FROM `bigquery-public-data.***.users` 
  WHERE reputation > 200000
  GROUP BY 1
  ORDER BY 1
) a
ORDER BY reputation_group

但是,如果您这样做,就更容易忘记 RANGE_BUCKET:

WITH buckets AS (
  SELECT IFNULL(LAG(max) OVER(ORDER BY grp), -10000000) min, *
  FROM UNNEST([400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000]) max WITH OFFSET grp
)


SELECT buckets.min, buckets.max, COUNTIF(reputation >= buckets.min AND reputation < buckets.max) c
FROM `bigquery-public-data.***.users`, buckets
WHERE reputation > 200000
GROUP BY 1,2
ORDER BY 1

或者:

SELECT IFNULL(min,0) min, max, COUNT(*) c
FROM (
  SELECT (SELECT MAX(x) FROM UNNEST(ranges) x WHERE x<reputation) min, (SELECT MIN(x) FROM UNNEST(ranges) x WHERE x>reputation) max
  FROM `bigquery-public-data.***.users` 
  , (SELECT [400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000] ranges) 
  WHERE reputation > 200000
)
GROUP BY 1, 2
ORDER BY 1

【讨论】:

谢谢你,Felipe,你的最后一个查询也很好并且有效,我希望 *** 允许多个答案,但他们目前不这样做。 不用担心。确实,您只能接受一个答案。但你可以投票赞成所有你喜欢的答案。 感谢提醒。 :) 如果您对 DataStudio 有很好的了解,如果您能看一下这里将不胜感激:***.com/questions/60243829/…【参考方案2】:

以下是 BigQuery 标准 SQL

#standardSQL
SELECT bucket, 
  FORMAT('%i - %i', IFNULL(ranges[SAFE_OFFSET(bucket - 1)] + 1, 0), ranges[SAFE_OFFSET(bucket)]) AS reputation_group, 
  COUNT(*) AS COUNT
FROM `bigquery-public-data.***.users`,
UNNEST([STRUCT([400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000] AS ranges)]),
UNNEST([RANGE_BUCKET(reputation, ranges)]) bucket 
WHERE reputation > 200000
GROUP BY 1, 2
ORDER BY bucket  

结果

Row bucket  reputation_group    COUNT    
1   0       0 - 400000          198  
2   1       400001 - 500000     23   
3   2       500001 - 600000     13   
4   3       600001 - 700000     12   
5   4       700001 - 800000     4    
6   5       800001 - 900000     5    
7   6       900001 - 1000000    2    
8   8       1100001 - 1200000   1    

【讨论】:

以上是关于在 bigquery 中使用 RANGE_BUCKET 时如何显示存储桶名称的主要内容,如果未能解决你的问题,请参考以下文章

在 Power BI 中使用 BigQuery 重复/嵌套字段

是否可以在 aws lambda 中使用 bigquery?

BigQuery -- 在公开共享项目中使用 UDF 的问题

在 BigQuery 的查询中使用 UDF 作为列

Bigquery:在 Bigquery 中计算余额或重写 SQL 脚本

如何在 Datalab 的 api 中使用 Bigquery 中的子查询?