【问题标题】:Use google bigquery to build histogram graph使用 google bigquery 构建直方图
【发布时间】:2013-03-06 01:35:35
【问题描述】:

如何编写使直方图渲染更容易的查询?

例如,我们有 1 亿人的年龄,我们想要绘制年龄 0-10、11-20、21-30 等的直方图/桶...查询是什么样的?

有人做过吗?您是否尝试将查询结果连接到 google 电子表格以绘制直方图?

【问题讨论】:

    标签: sql google-bigquery


    【解决方案1】:

    像这样写一个子查询:

    (SELECT '1' AS agegroup, count(*) FROM people WHERE AGE <= 10 AND AGE >= 0)
    

    然后你可以这样做:

    SELECT * FROM
    (SELECT '1' AS agegroup, count(*) FROM people WHERE AGE <= 10 AND AGE >= 0),
    (SELECT '2' AS agegroup, count(*) FROM people WHERE AGE <= 20 AND AGE >= 10),
    (SELECT '3' AS agegroup, count(*) FROM people WHERE AGE <= 120 AND AGE >= 20)
    

    结果如下:

    Row agegroup count 
    1   1       somenumber
    2   2       somenumber
    3   3       another number
    

    我希望这对你有帮助。当然在这个年龄段你可以写任何东西:'0 to 10'

    【讨论】:

      【解决方案2】:

      2019 update, with #standardSQL --Fh


      子查询的想法是有效的,就像“CASE WHEN”一样,然后按以下方式进行分组:

      SELECT COUNT(field1), bucket 
      FROM (
          SELECT field1, CASE WHEN age >=  0 AND age < 10 THEN 1
                              WHEN age >= 10 AND age < 20 THEN 2
                              WHEN age >= 20 AND age < 30 THEN 3
                              ...
                              ELSE -1 END as bucket
          FROM table1) 
      GROUP BY bucket
      

      或者,如果桶是规则的——你可以只划分并转换为一个整数:

      SELECT COUNT(field1), bucket 
      FROM (
          SELECT field1, INTEGER(age / 10) as bucket FROM table1)
      GROUP BY bucket
      

      【讨论】:

      • 您可以通过使用"0 &lt;= age &lt; 10""10 &lt;= age &lt; 20" 等字符串命名存储桶来使事情更清楚。另外,SUM(field1) 不是对年龄值求和吗?我想你想做SELECT 1 只计算桶中的每个年龄一次。
      • 这些查询是否应该使用 COUNT(field1) 而不是 SUM(field1)?
      • @MattFaus,0 &lt;= age &lt; 100 &lt;= age OR age &lt; 10,至少在 BigQuery 领域。
      • 我的命名建议是为了人类可读,而不是机器。
      • 是的@Valis——应该是COUNT(field1)
      【解决方案3】:

      您正在寻找一个单一的信息向量。我通常会这样查询:

      select
        count(*) as num,
        integer( age / 10 ) as age_group
      from mytable
      group by age_group 
      

      任意组都需要一个大的case 语句。它会很简单,但会更长。如果每个桶包含 N 年,我的示例应该没问题。

      【讨论】:

        【解决方案4】:

        您还可以使用quantiles 聚合运算符快速查看年龄分布。

        SELECT
          quantiles(age, 10)
        FROM mytable
        

        此查询的每一行都对应于年龄列表中该点的年龄。第一个结果是年龄排序列表的 1/10 岁,第二个是 2/10 岁,3/10 岁等。

        【讨论】:

        【解决方案5】:

        使用交叉连接来获取最小值和最大值(在单个元组上并不那么昂贵),您可以获得任何给定存储桶计数的标准化存储桶列表:

        select
          min(data.VAL) as min,
          max(data.VAL) as max,
          count(data.VAL) as num,
          integer((data.VAL-value.min)/(value.max-value.min)*8) as group
        from [table] data
        CROSS JOIN (SELECT MAX(VAL) as max, MIN(VAL) as min, from [table]) value
        GROUP BY group
        ORDER BY group 
        

        在这个例子中,我们得到了 8 个桶(非常不言自明)加上一个用于 null VAL

        【讨论】:

          【解决方案6】:

          使用#standardSQL 和辅助stats 查询,我们可以定义直方图应查看的范围。

          这里是 SFO 和 JFK 之间飞行的时间 - 有 10 个桶:

          WITH data AS ( 
              SELECT *, ActualElapsedTime datapoint
              FROM `fh-bigquery.flights.ontime_201903`
              WHERE FlightDate_year = "2018-01-01" 
              AND Origin = 'SFO' AND Dest = 'JFK'
          )
          , stats AS (
            SELECT min+step*i min, min+step*(i+1)max
            FROM (
              SELECT max-min diff, min, max, (max-min)/10 step, GENERATE_ARRAY(0, 10, 1) i
              FROM (
                SELECT MIN(datapoint) min, MAX(datapoint) max
                FROM data
              )
            ), UNNEST(i) i
          )
          
          SELECT COUNT(*) count, (min+max)/2 avg
          FROM data 
          JOIN stats
          ON data.datapoint >= stats.min AND data.datapoint<stats.max
          GROUP BY avg
          ORDER BY avg
          

          如果您需要整数,请参阅:https://stackoverflow.com/a/60159876/132438

          【讨论】:

            【解决方案7】:

            现在标准 SQL 中有 APPROX_QUANTILES 聚合函数。

            SELECT
                APPROX_QUANTILES(column, number_of_bins)
            ...    
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-10-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-12-11
              • 2014-02-15
              • 2014-02-16
              相关资源
              最近更新 更多