如何更新 BigQuery 中的多行

Posted

技术标签:

【中文标题】如何更新 BigQuery 中的多行【英文标题】:How to update multiple rows in BigQuery 【发布时间】:2019-08-22 11:53:43 【问题描述】:

我只在几周内使用 user_id(在此之前我只有 user_pseudo_id)”,所以我想在数据集的早期更新 user_id 值,它是 NULL。

我在这里找到了一个解决方案,但它不适合,因为每个 user_id 都有更多 user_pseudo_id

update multiple rows which is having null values

我的代码:

UPDATE `dataset.events`
    SET user_id = b.user_id
    FROM `dataset.events` a
        INNER JOIN (SELECT DISTINCT user_pseudo_id, user_id 
                    FROM `dataset.events`
                    WHERE user_id IS NOT NULL) b
            ON a.user_pseudo_id = b.user_pseudo_id
     WHERE a.user_id IS NULL

代码有效,但修改了 0 行并弹出此消息:“UPDATE/MERGE must match at most one source row for each target row”

更新: 我现在的日期:

user_pseudo_id____user_id

a___________________NULL a___________________空 b___________________空 c_____NULL a___________________111 b___________________111 c_____222

我想要什么:

user_pseudo_id____user_id

a___________________111 a___________________111 b___________________111 c_____222 a___________________111 b___________________111 c_____222

注意,具有 a 和 b 伪 ID 的用户是同一个用户,所以他们有一个 user_id。

【问题讨论】:

看起来每个 user_pseudo_id 都有多个 user_id。无论哪种情况,您会选择在更新中使用哪个值?尝试找到一个解决方案,其中每个 user_pseudo_id 都有一个 user_id(想想 MIN、MAX 等)。 user_pseudo_id 标记给定设备上的应用程序实例。 user_id 标记用户。有用户在不同的设备上使用该应用程序,所以如果多个user_pseudo_ids属于一个user_id是正常的。当然,反之亦然,一个 user_pseudo_id 只属于一个 user_id。我在我的数据中检查了它,并且有一堆带有更多 user_id 的 user_pseudo_id,但我将它们过滤掉了。问题还是一样。 :-/ @Akos`-您应该提供输入和预期输出的简化示例-以便我们更好地了解您的情况 所以,您想从这些对可用的条目中从表的其余部分“导出”缺少的 user_id - 对吗?请确认或澄清! 没错,我想要这个!我编辑了问题。 【参考方案1】:

以下是 BigQuery 标准 SQL

#standardSQL
WITH map AS (
  SELECT user_pseudo_id, MIN(user_id) user_id
  FROM `project.dataset.table`
  WHERE NOT user_id IS NULL
  GROUP BY user_pseudo_id
)
SELECT user_pseudo_id, IFNULL(t.user_ID, m.user_id)
FROM `project.dataset.table` t
LEFT JOIN map m
USING(user_pseudo_id)   

您可以使用您问题中的示例数据进行测试,使用上面的示例,如下例所示

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'a' user_pseudo_id, NULL user_id UNION ALL
  SELECT 'a', NULL UNION ALL
  SELECT 'b', NULL UNION ALL
  SELECT 'c', NULL UNION ALL
  SELECT 'a', '111' UNION ALL
  SELECT 'b', '111' UNION ALL
  SELECT 'c', '222' 
), map AS (
  SELECT user_pseudo_id, MIN(user_id) user_id
  FROM `project.dataset.table`
  WHERE NOT user_id IS NULL
  GROUP BY user_pseudo_id
)
SELECT user_pseudo_id, IFNULL(t.user_ID, m.user_id) user_id
FROM `project.dataset.table` t
LEFT JOIN map m
USING(user_pseudo_id)   

结果

Row user_pseudo_id  user_id  
1   a               111  
2   a               111  
3   b               111  
4   c               222  
5   a               111  
6   b               111  
7   c               222    

最后你可以将上面的代码包装成 UPDATE 语法,如下例所示

#standardSQL
UPDATE `project.dataset.table` t
SET user_id = IFNULL(t.user_ID, map.user_id)
FROM (
  SELECT user_pseudo_id, MIN(user_id) user_id
  FROM `project.dataset.table`
  WHERE NOT user_id IS NULL
  GROUP BY user_pseudo_id
) map
WHERE t.user_pseudo_id = map.user_pseudo_id

或者您可以只过滤行以更新 user_id 为 null 的位置,如下例所示

#standardSQL
UPDATE `project.dataset.table` t
SET user_id = map.user_id
FROM (
  SELECT user_pseudo_id, MIN(user_id) user_id
  FROM `project.dataset.table`
  WHERE NOT user_id IS NULL
  GROUP BY user_pseudo_id
) map
WHERE t.user_pseudo_id = map.user_pseudo_id
AND t.user_ID IS NULL

【讨论】:

以上是关于如何更新 BigQuery 中的多行的主要内容,如果未能解决你的问题,请参考以下文章

使用 Apache Beam 向 BigQuery 传播插入时如何指定 insertId

如何在 Google BigQuery 的记录中查询字符串?文档不工作

如何在 BigQuery SQL 中将字符串列拆分为多行单个单词和单词对?

BigQuery 中的标准 SQL - 从多行获取连接文本

如何在 BigQuery 中将多行聚合为一行?

Dataproc + BigQuery 示例 - 有可用的吗?