【问题标题】:如何使列与 Google Big Query 中的行一致
【发布时间】:2026-01-09 05:55:02
【问题描述】:

我正在执行数据 QA 测试。

我有这个查询来确定源表和目标表之间的任何错误。

select 
count(case when coalesce(x.col1,1) = coalesce(y.col1,1) then null else 1 end) as cnt_col1,
count(case when coalesce(x.col2,"1") = coalesce(y.col2,"1") then null else 1 end) as cnt_col2
from
`DatasetA.Table` x
OUTER JOIN
`DatasetB.Table` y
on x.col1 = y.col1

这个查询的输出是这样的:

col1, col2
null, null
null, null
1, null
null, 1

我需要在 200 个表上执行此测试,cols 的数量是动态的。上表只有两列,有的有50列。

我已经有了对表的查询,但我需要将所有测试的输出整合到一个输出中。我的计划是将每个查询整合到一个统一的输出中,并使用UNION ALL 将它们连接在一起。

输出集应该说:

COLUMN, COUNT_OF_ERRORS
cnt_col1, 1
cnt_col2, 1
...
cnt_col15, 0

我的问题是这样的。 如何反向旋转,以便实现我正在寻找的输出。

谢谢

【问题讨论】:

  • How do I reverse pivot this so I can achieve the output I'm looking for. - 可以通过在此处显示预期输出示例来可视化这一点!
  • 我做了...这是第三个代码块。
  • 我现在明白了——我不清楚
  • 您能否说明如何计算错误 - 根据您的示例,我会说 col1 有 1 个错误,col2 有 1 个错误,但在最终输出中,两者都显示为 0?
  • 这意味着根据您的示例(块 2),在您的预期输出(块 3)中,cnt_col1 的计数应为 1,而 cnt_col2 的计数应为 1 - 即使您可能认为这对于你的问题 - 但它 - 重要 - 呈现所有清晰和干净。 :o) 所以我们可以有效地提供帮助

标签: google-bigquery


【解决方案1】:

我如何反向旋转这个,以便我可以实现我正在寻找的输出。

假设你有表`data`

col1    col2    col3
----    ----    ----     
null    null    null     
null    null    1    
null    1       1    
1       null    1    
1       null    1    
1       null    1   

你需要将它反向旋转到

column      count_of_errors  
--------    ---------------
cnt_col1    3    
cnt_col2    1    
cnt_col3    5    

下面是 BigQuery 标准 SQL 并且正是这样做的

#standardSQL
WITH `data` AS (
  SELECT NULL AS col1, NULL AS col2, NULL AS col3 UNION ALL
  SELECT NULL, NULL, 1 UNION ALL
  SELECT 1, NULL, 1 UNION ALL
  SELECT NULL, 1, 1 UNION ALL
  SELECT 1, NULL, 1 UNION ALL
  SELECT 1, NULL, 1
)
SELECT r.* FROM (
  SELECT 
    [
    STRUCT<column STRING, count_of_errors INT64>
      ('cnt_col1', SUM(col1)),
      ('cnt_col2', SUM(col2)),
      ('cnt_col3', SUM(col3))
    ] AS row
  FROM `data`
), UNNEST(row) AS r   

它非常简单且友好,可以调整您在初始“数据”表中可能拥有的任意数量的列 - 您只需添加相应数量的 ('cnt_colN', SUM(colN)), - 可以手动完成,也可以编写简单的生成这些行(或整个查询)的脚本

【讨论】:

  • 我很高兴它有帮助!喜欢 BigQuery,也喜欢 SO,因为它提供了传递/分享知识和帮助人们的机会 :o)
【解决方案2】:

关于大数据中的“比较两个表”,我不认为做一些连接是最好的方法,因为连接通常很慢,然后你必须处理“外部”连接行的情况。

我在几年前就研究过这个主题 (https://community.hortonworks.com/articles/1283/hive-script-to-validate-tables-compare-one-with-an.html),现在我正试图将这些知识反向移植来比较 Hive 表和 BigQuery 表。

我的一个主要想法是使用一些校验和来确保一个表与另一个表完全相同。 这是一个“基本示例”:

with one_string as(
select concat( sessionid ,'|',referrercode ,'|',purchaseid ,'|',customerid ,'|', cast(bouncerateind as string),'|', cast( productpagevisit as string),'|', cast( itemordervalue as string),'|', cast( purchaseinsession as string),'|', cast( hit_time_gmt as string),'|',datedir ,'|',productcategory ,'|',post_cookies) as bigstring from bidwh2.omniture_2017_03_24_v2
),
shas as(
   select TO_BASE64( sha1( bigstring)) as sha from one_string
),
shas_prefix as(
   select substr( sha, 0 , 1) as prefix, sha from shas
),
shas_ordered as(
    select prefix, sha from shas_prefix order by sha
 ),
results_prefix as(
    select concat( prefix, ' ', TO_BASE64( sha1( STRING_AGG( sha, '|')))) as res from shas_ordered group by prefix
),
results_ordered as(
    select 1 as myall, res from results_prefix order by res
)
select SHA1( STRING_AGG( res, '|')) as sha from results_ordered group by myall;

因此,您对 2 个表中的每一个都执行此操作,并比较 2 个校验和数字。

最终的想法是有一个 Python 脚本(还没有完成,我希望我的公司允许我在完成后开源),它将执行以下操作:

  1. 计算一些“桶”的行数(分布良好的列具有相同校验和以大数为模的行组)并比较结果(因为如果行不匹配)。
  2. 如果计数不匹配,则直观地显示差异
  3. 使用存储桶/行技术 + 一些其他“存储桶/列”以类似于上例所示的方式执行一些校验和。并将所有这些校验和一起比较。
  4. 在校验和不匹配时直观地显示差异

于 2017 年 3 月 11 日编辑:脚本已完成,可在以下位置找到:https://github.com/bolcom/hive_compared_bq

【讨论】:

  • Sourygna,这是一个绝妙的策略,我想看看你在使用 Python 代码时如何实现它。但是,我的人说我必须识别那些不匹配的列,以确定我们是否有转换失败。对于行检查,这听起来很强大。谢谢你的建议。
  • 是的,第 3 点的想法是能够看到不匹配的行和列。我分为“列桶”以减少中间结果(校验和)的数量。这也意味着,当我展示第 4 点中的差异时,我将能够向最终用户只展示一些失败的列组(一个组将由大约 5 列组成)。让我们看看我能不能在接下来的几天内尽快完成,我能不能给你看一些结果。
  • 这里是我之前提到的Python脚本的项目:github.com/bolcom/hive_compared_bq
最近更新 更多