如何比较 BigQuery 中的两个数组?

Posted

技术标签:

【中文标题】如何比较 BigQuery 中的两个数组?【英文标题】:How do you compare two arrays in BigQuery? 【发布时间】:2017-04-27 19:36:44 【问题描述】:

我正在尝试加入两个表,每个表都有一个如下所示的数组列

SELECT a.id, b.value
FROM a INNER JOIN b
ON a.array IN b.array

SELECT a.id, b.value
FROM a INNER JOIN b
ON UNNEST(a.array) IN UNNEST(b.array)

根据this SO question,postgres 有像 >@ 这样的运算符来比较其中一个是否是另一个数组的子集( postgres doc page) 但 BigQuery 只允许将数组的一个元素与另一个数组进行比较,如下所示

a.arrayelement IN UNNEST(b.array)

可以在 BigQuery 中完成吗?

编辑

这是我正在使用的架构

WITH b AS (
      "ip": "192.168.1.1",
      "cookie": [
         "key": "apple",
          "value: "red"
        ,
         "key": "peach",
          "value: "pink"
        ,
         "key": "orange",
          "value: "orange"
        
      ]
    
    ,  "ip": "192.168.1.2",
      "cookie": [
         "key": "apple",
          "value: "red"
        ,
         "key": "orange",
          "value: "orange"
        
      ]
    
   ),
WITH a AS (
      "id": "12345",
      "cookie": [
         "key": "peach",
          "value: "pink"
        
      ]
    
    ,  "id": "67890",
      "cookie": [
         "key": "apple",
          "value: "red"
        ,
         "key": "orange",
          "value: "orange"
        ,

      ]
     
)

我期待如下输出

ip, id
192.168.1.1, 67890 
192.168.1.2, 67890 
192.168.1.2, 12345

它是以下 SO 的延续, How do I find elements in an array in BigQuery 。 我尝试使用子查询来比较其中一个数组的单个元素,但 BigQuery 返回一个错误,提示我有 “子查询太多”

【问题讨论】:

取决于实际的数组模式 - 这样做可以有不同的选择。您能否提供您的具体示例,这样就无需猜测要显示哪个选项 @MikhailBerlyant 始终感谢您的帮助。我添加了架构 以及基于该示例的预期输出是什么? 【参考方案1】:

这是一个替代解决方案,它避免在相关子查询中运行 JOIN,而是依赖于 IN UNNEST() 表达式 - 这应该会提供更好的性能:

#standardSQL
WITH a AS (
  SELECT 1 AS id, [2,4] AS a_arr UNION ALL
  SELECT 2, [3,5]
),
b AS (
  SELECT 11 AS value, [1,2,3,4] AS b_arr UNION ALL
  SELECT 12, [1,3,5,6]
)
SELECT a.id, b.value
FROM a , b
WHERE (SELECT LOGICAL_AND(a_i IN UNNEST(b.b_arr)) FROM UNNEST(a.a_arr) a_i)

【讨论】:

【参考方案2】:

试试下面的例子(BigQuery 标准 SQL)

#standardSQL
WITH a AS (
  SELECT 1 AS id, [2,4] AS a_arr UNION ALL
  SELECT 2, [3,5]
),
b AS (
  SELECT 11 AS value, [1,2,3,4] AS b_arr UNION ALL
  SELECT 12, [1,3,5,6]
)
SELECT a.id, b.value
FROM a , b , UNNEST([(SELECT ARRAY_LENGTH(a.a_arr) - COUNT(1) 
                      FROM UNNEST(a.a_arr) AS x 
                      JOIN UNNEST(b.b_arr)  AS y 
                      ON x = y)]) AS z
WHERE z = 0

它模仿下面的伪代码:

SELECT a.id, b.value
FROM a INNER JOIN b
ON a.array IN b.array  

如果您希望我将其应用于您的示例,请告诉我 - 或者您将先自己尝试 :o)

【讨论】:

进展如何?需要我加入吗? 我将您的逻辑应用于我的实际架构及其工作:D 现在我正在检查它是否可以在 WITH 子句中扩展到 1000 多行。我希望 BigQuery 不会大喊大叫我 太棒了。很高兴我们做到了:o) 我确实有一个问题。用 UNNEST 包围 z 表和不包围它有什么区别?我理解逻辑,但我想剖析 SQL 并查看实际行为......但我需要 UNNEST 才能使示例代码正常工作 引入 z 是一个技巧,它允许您为每个连接组合预先创建列,以便您可以直接在 WHERE 子句中使用它。否则,您需要将相应的子选择明确地作为额外的列放在输出中,然后用另一个选择包装它,您将在其中按匹配项过滤结果。这个想法是只留下那些共同元素的数量等于表 a 中数组中的元素数量的组合。尝试更多地玩这个,让我知道是否有更多问题

以上是关于如何比较 BigQuery 中的两个数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何关联多个 BigQuery 数组字段?

如何将每个给定长度的行的 Bigquery 表提取到 Google Storage 中的 csv 文件?

如何在bigquery中连接两个结构数组?

Pyspark 和 BigQuery 在 Google Dataproc 中使用两个不同的项目 ID

Cloud Dataflow 中的“辅助输入”是不是支持从 BigQuery 视图中读取?

连接 BigQuery 和 Google 表格 - 日期参数问题