简体   繁体   English

在 Bigquery 表中查找每行所在的范围

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM