如何在 BigQuery 中取消嵌套重复记录,一个数组给出列名,另一个给出列值?

Posted

技术标签:

【中文标题】如何在 BigQuery 中取消嵌套重复记录,一个数组给出列名,另一个给出列值?【英文标题】:How can I unnest a repeated record in BigQuery, with one array giving the column names and another giving column values? 【发布时间】:2021-04-30 12:44:21 【问题描述】:

我在 Google BigQuery 中工作,并且有一个包含两条重复记录的数据集:一条是元素名称,另一条是元素值。我的数据集的简化版本(只有 2 个条目)如下所示:

globalId Meta.name Meta.value
9200000104 ViewsL7D 2877
OldPrice 33.47
NewPrice 33.21
9200000783 ViewsL7D 19231
OldPrice 14.27
NewPrice 12.11

我想要的是这样的表格:

globalId ViewsL7D OldPrice NewPrice
9200000104 2877 33.47 33.21
9200000783 19231 14.27 12.11

我之前没有处理过重复记录,所以我真的不知道如何解决这个问题,但到目前为止我已经尝试使用以下代码: SELECT * FROM table LEFT JOIN UNNEST(cloudmetadata)

但是当我这样做时,我保留了重复的记录,只添加了六个额外的列,在名称和值之间交替。有人可以帮忙吗?

【问题讨论】:

【参考方案1】:

您可以简单地旋转表格

如果你有超过这三个肉名你必须使用动态sql

CREATE TABLE table1 (
  `globalId` varchar(10),
  `Meta.name` VARCHAR(8),
  `Meta.value` DECIMAL(10,2)
);
INSERT INTO table1
  (`globalId`, `Meta.name`, `Meta.value`)
VALUES
  ('9200000104', 'ViewsL7D', '2877'),
  ('9200000104', 'OldPrice', '33.47'),
  ('9200000104', 'NewPrice', '3321'),
  ('9200000783', 'ViewsL7D', '19231'),
  ('9200000783', 'OldPrice', '14.27'),
  ('9200000783', 'NewPrice', '12.11');
SELECT 
`globalId`,
MAX(IF (`Meta.name` = 'ViewsL7D',`Meta.value`, NULL  )) AS ViewsL7D,
MAX(IF (`Meta.name` = 'OldPrice',`Meta.value`, NULL  )) AS OldPrice,
MAX(IF (`Meta.name` = 'NewPrice',`Meta.value`, NULL  )) AS NewPrice
FROM table1

GROUP BY `globalId`
全球标识 |视图L7D |旧价格 |新价格 :--------- | --------: | --------: | --------: 9200000104 | 2877.00 | 33.47 | 3321.00 9200000783 | 19231.00 | 14.27 | 12.11

db小提琴here

【讨论】:

【参考方案2】:

考虑以下方法

select globalId, 
  max(if(name = 'ViewsL7D', value, null)) as ViewsL7D,
  max(if(name = 'OldPrice', value, null)) as OldPrice,
  max(if(name = 'NewPrice', value, null)) as NewPrice
from your_table t, t.Meta
group by globalId    

如果应用于您问题中的样本数据

输出是

【讨论】:

你有机会尝试吗?【参考方案3】:

鉴于您的桌子的形状,我想您有两个数组 namevalue 保存在 Meta 结构中。我使用以下内容重新创建了表:

WITH
  mydata AS (
  SELECT
    9200000104 AS globalid,
    STRUCT(["ViewsL7D",
      "OldPrice",
      "NewPrice"] AS name,
      [2877,
      33.47,
      33.21] AS value) AS Meta
  UNION ALL
  SELECT
    9200000783 AS globalid,
    STRUCT(["ViewsL7D",
      "OldPrice",
      "NewPrice"] AS name,
      [19231,
      14.27,
      12.11] AS value) AS Meta )

您想从那里取消嵌套数组并对其进行旋转:

SELECT
  globalid,
  MAX(IF(name="ViewsL7D",value, NULL)) AS ViewsL7D,
  MAX(IF(name="OldPrice",value, NULL)) AS OldPrice,
  MAX(IF(name="NewPrice",value, NULL)) AS NewPrice
FROM
  (SELECT
    globalid,
    Meta.name[OFFSET(offset_value)] name,
    Meta.value[OFFSET(offset_value)] value
  FROM mydata,
  UNNEST(Meta.value) value WITH OFFSET offset_value ORDER BY offset_value)
GROUP BY globalid 
ORDER BY
  globalid

它给出了这个

【讨论】:

以上是关于如何在 BigQuery 中取消嵌套重复记录,一个数组给出列名,另一个给出列值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在存储为字符串的 bigquery 字段中取消嵌套多个数组?

BigQuery 取消嵌套数组 - 获取重复项

Bigquery:UNNEST 重复与展平表性能

如何在 BigQuery 中取消嵌套多个数组?

如何在 BigQuery 标准 SQL 中取消嵌套多个数组

在 BigQuery 中展平嵌套和重复的结构(标准 SQL)