将嵌套列添加到BigQuery表中,并连接标准SQL中另一个嵌套列的值

时间:2019-09-10 15:08:19

标签: sql join nested google-bigquery bigquery-standard-sql

我有一个相当复杂的数据集,通过无法轻松调整的Airflow DAG导入到BigQuery表中。

此作业将数据提取到具有以下格式的表中:

| Line_item_id | Device         |
|--------------|----------------|
| 123          | 202; 5; 100    |
| 124          | 100; 2         |
| 135          | 504; 202; 2    |

此刻,我正在使用此查询(在BQ Web UI中以标准SQL编写)将设备ID拆分为单个嵌套行:

SELECT 
  Line_item_id,
  ARRAY(SELECT AS STRUCT(SPLIT(RTRIM(Device,';'),'; '))) as Device,

输出:

| Line_item_id | Device |
|--------------|--------|
| 123          | 202    |
|              | 203    |
|              | 504    |
| 124          | 102    |
|              | 2      |
| 135          | 102    |

我面临的困难是我有一个单独的匹配表,其中包含设备ID及其对应的名称。我需要将设备名称添加到上表中,作为其对应ID旁边的嵌套值。

匹配表如下所示(具有更多行):

| Device_id | Device_name |
|-----------|-------------|
| 202       | Smartphone  |
| 203       | AppleTV     |
| 504       | Laptop      |

我想要的理想输出是:

| Line_item_id | Device_id | Device_name |
|--------------|-----------|-------------|
| 123          | 202       | Android     |
|              | 203       | AppleTV     |
|              | 504       | Laptop      |
| 124          | 102       | iphone      |
|              | 2         | Unknown     |
| 135          | 102       | iphone      |

如果有人知道如何实现这一目标,我将不胜感激。

编辑:

戈登的解决方案可以完美地工作,但是除此之外,如果有人想在以后重新嵌套数据(因此您实际上会得到相同的表和其他嵌套行),这就是我最终得到的查询:

select t.line_item_id, ARRAY_AGG(STRUCT(d as id, ot.name as name)) as device
from first_table t cross join
     unnest(split(Device, '; ')) d join
     match_table ot
     on ot.id  = d
GROUP BY line_item_id

3 个答案:

答案 0 :(得分:1)

您可以将解析逻辑移至from子句,然后移至所需的join处:

select *
from (select 124 as line_item_id, '203; 100; 6; 2' as device) t cross join
     unnest(split(device, '; ')) d join
     other_table ot
     on ot.device = d;

答案 1 :(得分:0)

您需要的是[a-zA-Z]设备数组的内容,然后在与UNNEST元表结合后将其回滚:

devices

希望这会有所帮助。

答案 2 :(得分:0)

以下是BigQuery标准SQL的内容。不需要GROUP BY ...

#standardSQL
SELECT * EXCEPT(Device), 
  ARRAY(
    SELECT AS STRUCT Device_id AS id, Device_name AS name
    FROM UNNEST(SPLIT(REPLACE(Device, ' ', ''), ';')) Device_id WITH OFFSET
    JOIN `project.dataset.devices` 
    USING(Device_id)
    ORDER BY OFFSET
  ) Device
FROM `project.dataset.items`   

如果要应用于您的问题的样本数据-结果为

enter image description here

仅供参考:我使用以下数据进行测试

WITH `project.dataset.items` AS (
  SELECT 123 Line_item_id, '202; 5; 100' Device UNION ALL
  SELECT 124, '100; 2' UNION ALL
  SELECT 135, '504; 202; 2' 
), `project.dataset.devices` AS (
  SELECT '202' Device_id, 'Smartphone' Device_name UNION ALL
  SELECT '203', 'AppleTV' UNION ALL
  SELECT '504', 'Laptop' UNION ALL
  SELECT '5', 'abc' UNION ALL
  SELECT '100', 'xyz' UNION ALL
  SELECT '2', 'zzz'
)
相关问题