【问题标题】:efficient way to compare two tables in bigquery在 bigquery 中比较两个表的有效方法
【发布时间】:2018-12-21 01:07:35
【问题描述】:

我有兴趣比较两个表是否包含相同的数据。

我可以这样做:

#standardSQL
SELECT
    key1, key2
FROM
(
    SELECT 
    table1.key1,
    table1.key2,
    table1.column1 - table2.column1 as col1,
    table1.col2 - table2.col2 as col2
    FROM
        `table1` AS table1
    LEFT JOIN
        `table2` AS table2
    ON
        table1.key1 = table2.key1
    AND
        table1.key2 = table2.key2
)
WHERE 
    col1 != 0
OR
    col2 != 0

但是当我想比较所有数字列时,这有点困难,特别是如果我想对多个表组合进行比较。

因此我的问题是:是否有人知道有可能迭代所有数字列并将结果集限制为那些差异不为零的键?

【问题讨论】:

    标签: sql google-bigquery ansi-sql bigquery-standard-sql


    【解决方案1】:

    在标准 SQL 中,我们发现在我们的用例中使用了两个 EXCEPT DISTINCT 中的一个 UNION ALL

    (
      SELECT * FROM table1
      EXCEPT DISTINCT
      SELECT * from table2
    )
    
    UNION ALL
    
    (
      SELECT * FROM table2
      EXCEPT DISTINCT
      SELECT * from table1
    )
    

    这会在两个方向上产生差异:

    • table1 中不在 table2 中的行
    • table2 中不在 table1 中的行

    注意事项:

    • table1table2 的宽度必须相同,并且列的顺序和类型必须相同。
    • 这不适用于STRUCTARRAY 数据类型。您应该先通过UNNESTTO_JSON_STRING 转换这些数据类型。
    • 这也不能直接使用GEOGRAPHY,您必须先使用ST_AsText 转换为文本

    【讨论】:

    • 有什么好的方法可以在其中添加一列来告诉数据来自哪个表?
    • 我修改为SELECT 'table1' AS Tbl, * FROM (SELECT ... EXCEPT DISTINCT ...) UNION ALL SELECT 'table2' AS Tbl, * FROM (SELECT ... EXCEPT DISTINCT ...) 这也获得了结果中的表源。顺便说一句——总体上喜欢这种方法
    【解决方案2】:

    首先,我想提出您原始查询的问题

    主要问题是 1) 使用 LEFT JOIN ; 2) 使用 col != 0

    以下是如何修改它以真正捕获两个表的所有差异
    运行您的原始查询并低于一个 - 希望您会看到差异

    #standardSQL
    SELECT key1, key2
    FROM
    (
        SELECT 
        IFNULL(table1.key1, table2.key1) key1,
        IFNULL(table1.key2, table2.key2) key2,
        table1.column1 - table2.column1 AS col1,
        table1.col2 - table2.col2 AS col2
        FROM `table1` AS table1
        FULL OUTER JOIN `table2` AS table2
        ON table1.key1 = table2.key1
        AND table1.key2 = table2.key2
    )
    WHERE IFNULL(col1, 1) != 0
    OR    IFNULL(col2, 1) != 0
    

    或者您可以尝试针对虚拟数据运行原始版本和更高版本以查看差异

    #standardSQL
    WITH `table1` AS (
      SELECT 1 key1, 1 key2, 1 column1, 2 col2 UNION ALL
      SELECT 2, 2, 3, 4 UNION ALL
      SELECT 3, 3, 5, 6
    ), `table2` AS (
      SELECT 1 key1, 1 key2, 1 column1, 29 col2 UNION ALL
      SELECT 2, 2, 3, 4 UNION ALL
      SELECT 4, 4, 7, 8
    )
    SELECT key1, key2
    FROM
    (
        SELECT 
        IFNULL(table1.key1, table2.key1) key1,
        IFNULL(table1.key2, table2.key2) key2,
        table1.column1 - table2.column1 AS col1,
        table1.col2 - table2.col2 AS col2
        FROM `table1` AS table1
        FULL OUTER JOIN `table2` AS table2
        ON table1.key1 = table2.key1
        AND table1.key2 = table2.key2
    )
    WHERE IFNULL(col1, 1) != 0
    OR    IFNULL(col2, 1) != 0   
    

    其次,下面将高度简化您的整体查询

    #standardSQL
    SELECT 
      IFNULL(table1.key1, table2.key1) key1,
      IFNULL(table1.key2, table2.key2) key2
    FROM `table1` AS table1
    FULL OUTER JOIN `table2` AS table2
    ON table1.key1 = table2.key1
    AND table1.key2 = table2.key2
    WHERE TO_JSON_STRING(table1) != TO_JSON_STRING(table2)  
    

    您可以使用与上述相同的虚拟数据示例对其进行测试
    注意:在此解决方案中,您不需要选择特定列 - 它只是比较所有列!但是如果您只需要比较特定的列 - 您仍然需要像下面的示例中那样挑选它们

    #standardSQL
    SELECT 
      IFNULL(table1.key1, table2.key1) key1,
      IFNULL(table1.key2, table2.key2) key2
    FROM `table1` AS table1
    FULL OUTER JOIN `table2` AS table2
    ON table1.key1 = table2.key1
    AND table1.key2 = table2.key2
    WHERE TO_JSON_STRING((table1.column1, table1.col2)) != TO_JSON_STRING((table2.column1, table2.col2))
    

    【讨论】:

    • 谢谢,这回答了我的问题(即使我仍然只对比较数字感兴趣,但确实这是一种更好的方法)!
    • 我在此找到了一篇 Medium 帖子 BigQuery Table Comparison,其中讨论了全表比较、使用散列和键值比较。完整的表格比较类似于此处提供的解决方案。
    【解决方案3】:

    您需要指定哪些是数字列,但查看所有列的表示将进行快速比较:

    #standardSQL
    WITH table_a AS (
      SELECT 1 id, 2 n1, 3 n2
    ), table_b AS  (
      SELECT 1 id, 2 n1, 4 n2
    )
    
    
    SELECT id
    FROM table_a a
    JOIN table_b b
    USING(id)
    WHERE TO_JSON_STRING([a.n1, a.n2]) != TO_JSON_STRING([b.n1, b.n2])
    

    【讨论】:

    • 所以快速比较是指加快连接速度吗?但我还是得手动确定数字?
    • 是的,“快”,因为您必须编写更少的代码,但是 SQL 没有办法自省 AFAIK 列的类型
    • 不幸的是,这就是我想要的……即使它没有回答我的问题,感谢您向我展示了这种优化可能性!
    猜你喜欢
    • 2022-11-04
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    • 2023-02-08
    • 2021-04-27
    相关资源
    最近更新 更多