在 BigQuery 中,确定列何时与 UNION ALL 不匹配

In BigQuery, identify when columns do not match on UNION ALL

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 不会引发错误,因为两个 table 具有相同的列数(每个 3)。但是我收到错误的数据输出,因为列不匹配。而不是输出具有 4 列 nameagespeedstrength 的新 table 以及正确的值 + 缺失值的空值(这可能是首选),union all 保留顶行的 3 列。

有没有一种好方法可以发现列不匹配,而不是静默查询 returning 错误数据?有什么方法可以 return 一个错误,而不是一个成功的 table?我不确定如何在 SQL 中检查 2 table 中的列是否匹配。

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

中出错

table1table2 保存为 BigQuery 数据集中的 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 returns 信息包括列名称 它们的位置。我可以将这两个表连接在一起,然后检查名称是否匹配...

以下适用于 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