[英]Find the range where each row falls within on a Bigquery table
I have a lookup table like below, which helps add a description to total sales made by a company.我有一个如下所示的查找表,它有助于为公司的总销售额添加描述。
limit限制 | description描述 |
---|---|
99 99 | tens十 |
999 999 | hundreds数百 |
999,999 999,999 | thousands数千 |
999,999,999 999,999,999 | millions百万 |
999,999,999,999 999,999,999,999 | billions数十亿 |
For each row in my sales table, I would like to lookup the total sales and find the corresponding description (for example, if a company made sales worth $1,234,567 the description should be 'millions'. If a company made sales worth $999,999 the description should be thousands)对于我的销售表中的每一行,我想查找总销售额并找到相应的描述(例如,如果一家公司的销售额为 1,234,567 美元,那么描述应该是“百万”。如果一家公司的销售额为 999,999 美元,那么描述应该数以千计)
WITH lookup_table AS (SELECT limit, description FROM projectid.dataset.lookup)
SELECT total_sales, --logic-to-find-description AS description
FROM projectid.dataset.sales
Sample output样品 output
total_sales总销售额 | description描述 |
---|---|
89 89 | tens十 |
45,879 45,879 | thousands数千 |
12,254,785 12,254,785 | millions百万 |
What would be the best way to achieve this.实现这一目标的最佳方法是什么。
Try this:尝试这个:
with lookup_table as
(
select 99 as `limit`, 'tens' as description
union all select 999, 'hundreds'
union all select 999999, 'thousands'
union all select 999999999, 'millions'
union all select 999999999999, 'billions'
),
sales_table as
(
select 89 as total_sales
union all select 45879
union all select 12254785
union all select 999999
)
select t.total_sales,
(
select tt.description
from lookup_table tt
where t.total_sales <= tt.`limit`
order by tt.`limit`
limit 1
) as description
from sales_table t
;
Or this:或这个:
with lookup_table as
(
select 99 as `limit`, 'tens' as description
union all select 999, 'hundreds'
union all select 999999, 'thousands'
union all select 999999999, 'millions'
union all select 999999999999, 'billions'
),
sales_table as
(
select 89 as total_sales
union all select 45879
union all select 12254785
union all select 999999
)
select t.total_sales,
t2.description,
from sales_table t
left join (
select tt.`limit`,
tt.description,
ifnull(lag(tt.`limit`) over(order by tt.`limit`)+1,0) as prev_value
from lookup_table tt
) t2 on t.total_sales between t2.prev_value and t2.`limit`;
Choose the one, which will be faster)选择一个,会更快)
Consdier using RANGE_BUCKET function, Consdier 使用RANGE_BUCKET function,
WITH lookup_table AS (
SELECT ANY_VALUE(description) description, ARRAY_AGG(`limit` ORDER BY `limit`) limits
FROM UNNEST([1, 2, 3, 6, 9]) n, UNNEST([CAST(POW(10, n) AS INT64)]) `limit`,
UNNEST([STRUCT(['tens', 'hundreds', 'thousands', 'millions', 'billions'] AS description)])
),
sales AS (
SELECT * FROM UNNEST([9, 89, 99, 100, 1000, 45879, 12254785]) total_sales
)
SELECT total_sales,
description[SAFE_OFFSET(RANGE_BUCKET(total_sales, limits) - 1)] AS description
FROM sales, lookup_table;
+-----+-------------+-------------+
| Row | total_sales | description |
+-----+-------------+-------------+
| 1 | 9 | null |
| 2 | 89 | tens |
| 3 | 99 | tens |
| 4 | 100 | hundreds |
| 5 | 1000 | thousands |
| 6 | 45879 | thousands |
| 7 | 12254785 | millions |
+-----+-------------+-------------+
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.