如何使用包含所有映射的查找表替换多列中的值?
Posted
技术标签:
【中文标题】如何使用包含所有映射的查找表替换多列中的值?【英文标题】:How do I replace values in multiple columns using a lookup table that contains all the mappings? 【发布时间】:2019-04-03 09:37:13 【问题描述】:我有一个表格,其中包含 4 列产品代码(以及其他列)。我有另一个表,其中包含一列all_codes
,另一列包含代码的descriptions
。
如何将第一个表中的多列代码加入(或替换)到第二个表中的描述?
我已设法通过加入 ontbl1.code1 = tbl2.all_codes
来使用替换功能来获取我的一个专栏的描述,但无法使其扩展到工作
tbl1.code2 = tbl2.all_codes, tbl1.code3 = tbl2.all_codes
等等等等
表 1
OrderNo | Style_code | Color_code | Country_code
-------------|-------------|--------------|---------------
21540 | abc | kdx | plo
21541 | gcs | kdy | pla
21542 | wer | kdz | plh
21543 | abc | kdx | pld
21544 | gcs | kdy | plo
表 2
all_codes | description
------------|-----------------
abc | plain
gcs | vintage
wer | modern
kdx | white
kdy | gray
kdz | black
plo | USA
pla | Mexico
plh | Canada
pld | Brazil
期望的输出
OrderNo | Style_desc | Color_desc | Country_desc
-------------|-------------|--------------|---------------
21540 | plain | white | USA
21541 | vintage | gray | Mexico
21542 | modern | black | Canada
21543 | plain | white | Brazil
21544 | vintage | gray | USA
谁能帮我找出最好的方法来做到这一点?
【问题讨论】:
你能提供一个表结构的样本吗? 【参考方案1】:你想要多个join
s:
select t1.orderNo, acs.description as style_desc,
acc.description as color_desc,
acco.description as country_desc
from table1 t1 left join
all_codes acs
on t1.style_code = acs.code left join
all_codes acc
on t1.color_code = acc.code left join
all_codes acco
on t1.country_code = acco.code ;
此版本使用left join
,以防任何值与参考表不匹配。
【讨论】:
【参考方案2】:谁能帮我找出最好的方法来做到这一点?
以下选项适用于 BigQuery 标准 SQL。如果不是最好的 - 绝对是不错的尝试。假设 all_codes 表没有那么大,所以这些代码的数组是可管理的......
#standardSQL
CREATE TEMP FUNCTION code_mapping(code STRING, all_codes ARRAY<STRUCT<all_codes STRING, description STRING>>) AS ((
SELECT description FROM UNNEST(all_codes) WHERE code = all_codes
));
SELECT OrderNo,
code_mapping(Style_code, codes) Style_desc,
code_mapping(Color_code, codes) Color_desc,
code_mapping(Country_code, codes) Country_desc
FROM `project.dataset.table1`
CROSS JOIN (SELECT ARRAY_AGG(t) codes FROM `project.dataset.table2` t)
您可以使用您问题中的示例数据进行测试,如以下示例所示
#standardSQL
CREATE TEMP FUNCTION code_mapping(code STRING, all_codes ARRAY<STRUCT<all_codes STRING, description STRING>>) AS ((
SELECT description FROM UNNEST(all_codes) WHERE code = all_codes
));
WITH `project.dataset.table1` AS (
SELECT 21540 OrderNo, 'abc' Style_code, 'kdx' Color_code, 'plo' Country_code UNION ALL
SELECT 21541, 'gcs', 'kdy', 'pla' UNION ALL
SELECT 21542, 'wer', 'kdz', 'plh' UNION ALL
SELECT 21543, 'abc', 'kdx', 'pld' UNION ALL
SELECT 21544, 'gcs', 'kdy', 'plo'
), `project.dataset.table2` AS (
SELECT 'abc' all_codes, 'plain' description UNION ALL
SELECT 'gcs', 'vintage' UNION ALL
SELECT 'wer', 'modern' UNION ALL
SELECT 'kdx', 'white' UNION ALL
SELECT 'kdy', 'gray' UNION ALL
SELECT 'kdz', 'black' UNION ALL
SELECT 'plo', 'USA' UNION ALL
SELECT 'pla', 'Mexico' UNION ALL
SELECT 'plh', 'Canada' UNION ALL
SELECT 'pld', 'Brazil'
)
SELECT OrderNo,
code_mapping(Style_code, codes) Style_desc,
code_mapping(Color_code, codes) Color_desc,
code_mapping(Country_code, codes) Country_desc
FROM `project.dataset.table1`
CROSS JOIN (SELECT ARRAY_AGG(t) codes FROM `project.dataset.table2` t)
结果
Row OrderNo Style_desc Color_desc Country_desc
1 21540 plain white USA
2 21541 vintage gray Mexico
3 21542 modern black Canada
4 21543 plain white Brazil
5 21544 vintage gray USA
【讨论】:
有趣的方法,我没想过使用函数。我的 all_codes 表是 30000 长,而 orders 表是 1500000,所以它可能有点计算密集。 @MartinD - 30K 并没有那么大,无法打包到数组中。你真的试过吗?请尝试让我们知道 :o)以上是关于如何使用包含所有映射的查找表替换多列中的值?的主要内容,如果未能解决你的问题,请参考以下文章
如何基于查找数据框创建数据框并在特定列中的动态和映射值上创建多列
如何在SQL Server 2012中动态替换表中的所有值?