【问题标题】:In BigQuery, identify when columns do not match on UNION ALL在 BigQuery 中,确定 UNION ALL 上的列何时不匹配
【发布时间】:2020-08-28 17:26:37
【问题描述】:
with
  table1 as (
    select 'joe' as name, 17 as age, 25 as speed
  ),
  table2 as (
    select 'nick' as name, 21 as speed, 23 as strength
  )

select * from table1
union all
select * from table2

在 Google BigQuery 中,此 union all 不会引发错误,因为两个表的列数相同(每列 3 个)。但是我收到错误的数据输出,因为列不匹配。 union all 不是输出一个包含 4 列 nameagespeedstrength 的新表,其中包含正确的值 + 缺失值的空值(这可能是首选),union all 保留了 3 列顶行。

有没有一种很好的方法来捕获列不匹配,而不是查询静默返回错误数据?与成功的表相反,有什么方法可以返回错误吗?我不确定如何在 SQL 中检查 2 个表中的列是否匹配。

编辑:在此示例中,可以清楚地看到列不匹配,但是在我们的数据中,我们有 100 多列,我们希望避免出现在联合所有

【问题讨论】:

  • 在使用 union all 的情况下,您始终需要指定列名,并且在使用 union all 时,所有数据集的列顺序应该相同
  • 是的,我知道在使用union all 时列顺序应该相同。我的问题是是否有一种方法可以计算出列名+顺序实际上是相同的。
  • 重点是:当你做UNION ALL时不要使用*作为投影,而是明确列出列。
  • 我了解最佳实践。我只是问是否有可能在列名不匹配的情况下捕获/处理错误
  • 您是要在“运行时”还是“设计时”中进行制作?换句话说 - 可以吗,只是先比较架构,如果所有的洁净比单独的查询运行你的联合所有东西都好? - 哦,好的 - 这正是你刚刚回答的内容

标签: sql google-bigquery union-all


【解决方案1】:

以下是 BigQuery 标准 SQL 并使用 BQ 的脚本功能

DECLARE statement STRING;
SET statement = (
  WITH  table1_columns AS (
    SELECT column FROM (SELECT * FROM `project.dataset.table1` LIMIT 1) t,
    UNNEST(REGEXP_EXTRACT_ALL(TRIM(TO_JSON_STRING(t), '{}'), r'"([^"]*)":')) column
  ), table2_columns AS (
    SELECT column FROM (SELECT * FROM `project.dataset.table2` LIMIT 1) t,
    UNNEST(REGEXP_EXTRACT_ALL(TRIM(TO_JSON_STRING(t), '{}'), r'"([^"]*)":')) column
  ), all_columns AS (
    SELECT column FROM table1_columns UNION DISTINCT SELECT column FROM table2_columns
  )
  SELECT (
      SELECT 'SELECT ' || STRING_AGG(IF(t.column IS NULL, 'NULL as ', '') || a.column, ', ') || ' FROM `project.dataset.table1` UNION ALL '
      FROM all_columns a LEFT JOIN table1_columns t USING(column)
    ) || (
      SELECT 'SELECT ' || STRING_AGG(IF(t.column IS NULL, 'NULL as ', '') || a.column, ', ') || ' FROM `project.dataset.table2`'
      FROM all_columns a LEFT JOIN table2_columns t USING(column)
    ) 
);
EXECUTE IMMEDIATE statement;   

当应用于您问题的样本数据时 - 输出是

Row name    age     speed   strength     
1   joe     17      25      null     
2   nick    null    21      23   

【讨论】:

    【解决方案2】:

    在 BigQuery 的数据集中将 table1table2 保存为 2 个表后,我使用元数据和 INFORMATION_SCHEMA 检查列是否匹配。

    SELECT *
    FROM models.INFORMATION_SCHEMA.COLUMNS
    where table_name = 'table1'
    
    SELECT *
    FROM models.INFORMATION_SCHEMA.COLUMNS
    where table_name = 'table2'
    

    INFORMATION_SCHEMA.COLUMNS 返回的信息包括列名它们的位置。我可以将这两个表连接在一起,然后检查名称是否匹配...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 2019-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多