当行没有匹配的 LEFT JOIN 时,BigQuery 正在创建一个 NULL 结构

Posted

技术标签:

【中文标题】当行没有匹配的 LEFT JOIN 时,BigQuery 正在创建一个 NULL 结构【英文标题】:BigQuery is creating a STRUCT of NULLs when a row has no matching LEFT JOIN 【发布时间】:2020-11-27 07:45:48 【问题描述】:

我有一个名为models 的表。我有另一个名为labelled_data 的表,其中包含modelIdclassId。对于models 中的每一行,我需要计算每个classIdlabelled_data 中出现的次数。

以下 BigQuery 结果的列 classARRAYSTRUCTs。

WITH labelled_data AS(
  SELECT
    modelId,
    classId,
    COUNT(*) as count 
  FROM `abc.xyz.labelled_data`
  GROUP BY 1, 2
)

SELECT
  m.id,
  ARRAY_AGG(
    STRUCT(ld.classId AS id, ld.count)
  ) AS class,
FROM `abc.xyz.models` m
LEFT JOIN labelled_data AS ld ON ld.modelId = m.id
GROUP BY 1

问题在于,如果modelslabelled_data 之间没有匹配的LEFT JOIN,则class 包含一个STRUCT 元素,其元素为NULL

以下是 JSON 格式的大多数行的样子:


    "id": "43A4BBA0-7D3D-466B-B893-CE1397223EB6",
    "class": [
      
        "id": "F0CD7177-2608-4DA3-90F4-69DF435E3C3B",
        "count": "42"
      ,
      
        "id": "25FB2670-FBA8-4961-B4BC-535776FDE6D3",
        "count": "40"
      
    ]

这是一个有问题的行:


    "id": "428E6D3C-98A3-4B9E-BB50-DCD589C6E321",
    "class": [
      
        "id": null,
        "count": null
      
    ]

我希望得到的结果是:


    "id": "428E6D3C-98A3-4B9E-BB50-DCD589C6E321",
    "class": null

请注意,我不能从结果中排除该行。关于如何实现这一点的任何想法?

【问题讨论】:

【参考方案1】:

您可以使用case 表达式来确保至少有一个匹配行:

WITH (...)
SELECT
    m.id,
    CASE WHEN COUNT(ld.modelid) > 0
        THEN ARRAY_AGG(STRUCT(ld.classId AS id, ld.count)) 
    END AS class,
FROM `abc.xyz.models` m
LEFT JOIN labelled_data AS ld ON ld.modelId = m.id
GROUP BY 1

【讨论】:

以上是关于当行没有匹配的 LEFT JOIN 时,BigQuery 正在创建一个 NULL 结构的主要内容,如果未能解决你的问题,请参考以下文章

left joinright join和inner join

SQL的JOIN语法解析(inner join, left join, right join, full outer join的区别)

SQL SERVER LEFT JOIN, INNER JOIN, RIGHT JOIN

left join一些小坑

MySQL 数据库中 left outer join 和 left join 啥区别

join连接的五种方式的简单使用案例(Inner join,Left join,Right join