【问题标题】:Create ranges based on the data根据数据创建范围
【发布时间】:2020-02-10 19:56:47
【问题描述】:

我的产品以不同的价格出售。我想看看在特定价格范围内售出了多少产品。为此,我需要查看数据并查看如何划分范围,然后获取该范围内的产品数量。

数据如下-

Product        Price sold
   A              4.5
   B              45.7
   C              20
   D              20.1
   E              36.8
   F              50

例如,对于上述数据,我看到最小值为 4.5,最大值为 50。因此,我决定将价格范围划分为 - 0-10$、11-20$、21-30$、30- 40 美元,40-50 美元

所以,结果应该是这样的-

Range           No. of products sold
0-10                    1
11-20                   2
21-30                   0
30-40                   1
40-50                   2

价格是浮动的,因此范围应考虑浮动值。这可能吗?

【问题讨论】:

    标签: sql google-bigquery


    【解决方案1】:

    当前的答案似乎都没有回答这个问题:“我如何生成范围”(因为两个答案都假定范围为 0-50)。

    您似乎想要的是直方图,您可以在这里找到答案:

    现在,如果你想在每个桶之间循环:

    
    WITH data AS (
      SELECT * FROM  `fh-bigquery.public_dump.gdp_capita`
    ), min_and_max AS (
      SELECT MIN(gdp_capita) min, MAX(gdp_capita) max
      FROM data
    ), generate_buckets AS (
      SELECT x bucket_min
        , IFNULL(LEAD(x) OVER(ORDER BY x), 1+(SELECT max FROM min_and_max)) bucket_max 
      FROM UNNEST(generate_array(
        (SELECT 0 FROM min_and_max) # min or 0, depending on your start
        , (SELECT max FROM min_and_max)
        , (SELECT POW(10, fhoffa.x.int(LOG10(max-min)))/10 FROM min_and_max) # log10 for round order of 10 steps
      )) x
    )
    
    SELECT *
    FROM generate_buckets
    

    有了这些桶,你现在可以得到一个直方图:

    SELECT bucket_min, bucket_max, COUNT(*) c
    FROM generate_buckets
    JOIN data
    ON data.gdp_capita >= bucket_min AND data.gdp_capita < bucket_max 
    GROUP BY 1,2 
    ORDER BY 1
    

    如果你还需要 0 个元素的桶:

    SELECT * REPLACE(IFNULL(c,0) AS c)
    FROM (
      SELECT bucket_min, bucket_max, COUNT(*) c
      FROM generate_buckets
      JOIN data
      ON data.gdp_capita >= bucket_min AND data.gdp_capita < bucket_max AND data.one=generate_buckets.one
      GROUP BY 1,2 
      ORDER BY 1
    ) 
    RIGHT JOIN generate_buckets USING(bucket_min, bucket_max)
    

    【讨论】:

    • as both answers assume a range 0-50 - 这是不正确的。至少在我的回答中,您可以设置/在内联或查找表中设置任何范围
    • 我的意思是 - 两个答案都带来了固定代码桶。我想添加一个答案,在给定特定数据的情况下选择自己的范围。无论如何,用户似乎对当前接受的答案很满意:)
    • 当然,我仍然看不到我的答案中的范围是如何固定的 - 我认为它非常通用并且允许使用任何范围:o(
    • 我的意思是“固定”,因为“用户必须输入用户想要使用的任何范围”。但是问题的标题是“根据数据创建范围”,所以我想回答我将如何根据表格中显示的数据创建范围。
    • 哦,我现在明白你的意思了:o)
    【解决方案2】:

    以下是 BigQuery 标准 SQL

    #standardSQL
    WITH price_ranges AS (
      SELECT '0-10' price_range UNION ALL 
      SELECT '11-20' UNION ALL 
      SELECT '21-30' UNION ALL 
      SELECT '30-40' UNION ALL 
      SELECT '40-50' 
    )
    SELECT price_range, COUNT(1) number_sold
    FROM `project.dataset.table`
    JOIN price_ranges 
    ON CAST(price_sold AS INT64)
      BETWEEN CAST(SPLIT(price_range, '-')[OFFSET(0)] AS INT64) 
      AND CAST(SPLIT(price_range, '-')[OFFSET(1)] AS INT64)
    GROUP BY price_range
    -- ORDER BY price_range
    

    如果适用于您问题的样本数据 - 结果是

    Row price_range number_sold  
    1   0-10        1    
    2   11-20       2    
    3   30-40       1    
    4   40-50       2    
    

    【讨论】:

      【解决方案3】:

      您可以使用generate_array()。我将其表述为:

      select lb, lb + 10 as ub, count(d.product)
      from unnest(generate_array(0, 50, 10)) lb left join
           data d
           on d.price >= lb and
              d.price < lb + 10
      group by lb
      order by lb;
      

      您可以将下限和上限连接在一起,但将它们保持在两列中似乎很有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多