Сравните таблицы и извлеките их различия с помощью стандартного SQL
Сравнение таблиц в BigQuery — важная задача при тестировании результатов конвейеров данных и запросов перед их реализацией. Возможность сравнения таблиц позволяет обнаруживать любые изменения или несоответствия в данных, гарантируя, что данные остаются точными и непротиворечивыми.
В этой статье мы покажем, как сравнивать две (или более) таблицы в BigQuery и извлекать записи, которые различаются (если они есть). В частности, мы покажем, как сравнивать таблицы с одинаковыми столбцами, а также таблицы с разным количеством столбцов.
Во-первых, давайте начнем с создания двух таблиц с некоторыми фиктивными значениями, на которые мы затем будем ссылаться в этом руководстве, чтобы продемонстрировать несколько различных концепций.
-- Create the first table CREATE TABLE `temp.tableA` ( `first_name` STRING, `last_name` STRING, `is_active` BOOL, `no_of_purchases` INT ) INSERT `temp.tableA` (first_name, last_name, is_active, no_of_purchases) VALUES ('Bob', 'Anderson', True, 12), ('Maria', 'Brown', False, 0), ('Andrew', 'White', True, 4) -- Create the second table CREATE TABLE `temp.tableB` ( `first_name` STRING, `last_name` STRING, `is_active` BOOL, `no_of_purchases` INT ) INSERT `temp.tableB` (first_name, last_name, is_active, no_of_purchases) VALUES ('Bob', 'Anderson', True, 12), ('Maria', 'Brown', False, 0), ('Andrew', 'White', True, 6), ('John', 'Down', False, 0)
Сравнение записей таблиц с одинаковыми столбцами
Теперь, когда мы создали два примера таблиц, вы должны были заметить, что между ними есть несколько различий.
SELECT * FROM `temp.tableA`; +------------+-----------+-----------+-----------------+ | first_name | last_name | is_active | no_of_purchases | +------------+-----------+-----------+-----------------+ | Bob | Anderson | true | 12 | | Andrew | White | true | 4 | | Maria | Brown | false | 0 | +------------+-----------+-----------+-----------------+ SELECT * FROM `temp.tableB`; +------------+-----------+-----------+-----------------+ | first_name | last_name | is_active | no_of_purchases | +------------+-----------+-----------+-----------------+ | Bob | Anderson | true | 12 | | Andrew | White | true | 6 | | Maria | Brown | false | 0 | | John | Down | false | 0 | +------------+-----------+-----------+-----------------+
Теперь предположим, что таблица temp.tableB
является последней версией некоторого набора данных, тогда как temp.tableA
является более старой, и мы хотели бы увидеть фактические различия (с точки зрения записей) между двумя таблицами, все, что нам нужно, это следующий запрос:
WITH table_a AS (SELECT * FROM `temp.tableA`), table_b AS (SELECT * FROM `temp.tableB`), rows_mismatched AS ( SELECT 'tableA' AS table_name, * FROM ( SELECT * FROM table_a EXCEPT DISTINCT SELECT * FROM table_b ) UNION ALL SELECT 'tableB' AS table_name, * FROM ( SELECT * FROM table_b EXCEPT DISTINCT SELECT * FROM table_a ) ) SELECT * FROM rows_mismatched
Теперь результат будет содержать все наблюдаемые различия между таблицами вместе со ссылкой на имя таблицы, в которой были найдены записи.
В наших конкретных примерах таблицы A и B имели разницу в двух записях; Первая запись, похоже, является записью для Andrew White
, так как у этого человека другое значение для поля no_of_purchases
. Кроме того, в таблице tableB
есть одна дополнительная запись, которой нет даже в таблице tableA
.
+------------+------------+-----------+-----------+-----------------+ | table_name | first_name | last_name | is_active | no_of_purchases | +------------+------------+-----------+-----------+-----------------+ | tableB | John | Down | false | 0 | | tableB | Andrew | White | true | 6 | | tableA | Andrew | White | true | 4 | +------------+------------+-----------+-----------+-----------------+
Примечание. Если вы не знакомы с предложением WITH
и общими табличными выражениями (CTE) в SQL, обязательно прочитайте следующую статью:
Сравнение записей таблиц с разными столбцами
Теперь предположим, что вы хотите сравнить записи между двумя таблицами, имеющими разное количество столбцов. Очевидно, нам пришлось бы проводить сравнение яблок с яблоками, что означает, что нам каким-то образом нужно извлечь только общие поля из обеих таблиц, чтобы иметь возможность выполнить значимое сравнение.
Давайте заново создадим наши таблицы, чтобы сгенерировать некоторые несоответствующие столбцы, чтобы мы могли затем продемонстрировать, как справляться с этими случаями:
-- Create the first table CREATE TABLE `temp.tableA` ( `first_name` STRING, `last_name` STRING, `is_active` BOOL, `dob` STRING ) INSERT `temp.tableA` (first_name, last_name, is_active, dob) VALUES ('Bob', 'Anderson', True, '12/02/1993'), ('Maria', 'Brown', False, '10/05/2000'), ('Andrew', 'White', True, '14/12/1997') -- Create the second table CREATE TABLE `temp.tableB` ( `first_name` STRING, `last_name` STRING, `is_active` BOOL, `no_of_purchases` INT ) INSERT `temp.tableB` (first_name, last_name, is_active, no_of_purchases) VALUES ('Bob', 'Anderson', True, 12), ('Maria', 'Brown', True, 0), ('Andrew', 'White', True, 6), ('John', 'Down', False, 0)
Теперь наши новые таблицы имеют только три общих столбца, а именно first_name
, last_name
и is_active
.
SELECT * FROM `temp.tableA`; +------------+-----------+-----------+--------------+ | first_name | last_name | is_active | dob | +------------+-----------+-----------+--------------+ | Bob | Anderson | true | '12/02/1993' | | Andrew | White | true | '10/05/2000' | | Maria | Brown | false | '14/12/1997' | +------------+-----------+-----------+--------------+ SELECT * FROM `temp.tableB`; +------------+-----------+-----------+-----------------+ | first_name | last_name | is_active | no_of_purchases | +------------+-----------+-----------+-----------------+ | Bob | Anderson | true | 12 | | Andrew | White | true | 6 | | Maria | Brown | false | 0 | | John | Down | false | 0 | +------------+-----------+-----------+-----------------+
Теперь, если мы попытаемся запустить запрос, который мы выполнили в предыдущем разделе, где две таблицы имели одинаковые столбцы, мы получим эту ошибку:
Column 4 in EXCEPT DISTINCT has incompatible types: STRING, INT64 at [13:7]
Это абсолютно нормально, учитывая, что в наших таблицах больше нет соответствующих столбцов. Нам нужно немного изменить наш первоначальный запрос, чтобы самые первые CTE выбирали только взаимные столбцы для каждой таблицы. Наш запрос будет выглядеть следующим образом:
WITH table_a AS ( SELECT first_name, last_name, is_active FROM `temp.tableA` ), table_b AS ( SELECT first_name, last_name, is_active FROM `temp.tableB` ), rows_mismatched AS ( SELECT 'tableA' AS table_name, * FROM ( SELECT * FROM table_a EXCEPT DISTINCT SELECT * FROM table_b ) UNION ALL SELECT 'tableB' AS table_name, * FROM ( SELECT * FROM table_b EXCEPT DISTINCT SELECT * FROM table_a ) ) SELECT * FROM rows_mismatched
Таблицы, созданные в этом разделе, имели следующие несоответствия (при рассмотрении только их общих столбцов):
- Запись для
Maria Brown
имеет отличия в столбцеis_active
- В таблице
tableB
есть одна дополнительная запись (John Down
), которой нет вtableA
.
Эти различия можно наблюдать в результатах запроса, представленных ниже:
+------------+------------+-----------+-----------+ | table_name | first_name | last_name | is_active | +------------+------------+-----------+-----------+ | tableB | Maria | Brown | false | | tableB | John | Down | false | | tableA | Maria | Brown | true | +------------+------------+-----------+-----------+
Последние мысли
В этой статье мы предоставили подробное руководство о том, как сравнивать таблицы в BigQuery. Мы подчеркнули важность этой задачи для обеспечения точности и согласованности данных и продемонстрировали несколько методов сравнения таблиц с одинаковыми столбцами, а также таблиц с разным количеством столбцов. Мы также рассмотрели процесс извлечения записей, различающихся между таблицами (если они есть).
В целом, цель этой статьи — предоставить читателям необходимые инструменты и знания для эффективного и действенного сравнения таблиц в BigQuery. Я надеюсь, что вы сочли полезным!
Стать участником и читать все истории на Medium. Ваш членский взнос напрямую поддерживает меня и других писателей, которых вы читаете. Вы также получите полный доступ ко всем историям на Medium.
Статьи по теме, которые вам также могут понравиться