根据数据创建范围
Posted
技术标签:
【中文标题】根据数据创建范围【英文标题】: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
价格是浮动的,因此范围应考虑浮动值。这可能吗?
【问题讨论】:
【参考方案1】:当前的答案似乎都没有回答这个问题:“我如何生成范围”(因为两个答案都假定范围为 0-50)。
您似乎想要的是直方图,您可以在这里找到答案:
https://***.com/a/56447260/132438现在,如果你想在每个桶之间循环:
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;
您可以将下限和上限连接在一起,但将它们保持在两列中似乎很有用。
【讨论】:
以上是关于根据数据创建范围的主要内容,如果未能解决你的问题,请参考以下文章