如何使用包含所有映射的查找表替换多列中的值?

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】:

你想要多个joins:

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)

以上是关于如何使用包含所有映射的查找表替换多列中的值?的主要内容,如果未能解决你的问题,请参考以下文章

如何基于查找数据框创建数据框并在特定列中的动态和映射值上创建多列

如何使表格列在Angular 2中冻结的多列可滚动?

如何在SQL Server 2012中动态替换表中的所有值?

excel中,表1A列 包含表2A列所有内容,如何筛选出表1与表2相同的所有内容

如何根据另一个字典查找和替换一个字典中的值

如何将包含数组中的值的熊猫列扩展到多列?