#sql #google-bigquery #pivot #aggregate-functions
#google-bigquery
Вопрос:
Я выполняю тестирование качества данных.
У меня есть этот запрос, чтобы установить любые ошибки между исходной таблицей и целевой таблицей.
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
Мой вопрос заключается в следующем.
Как мне изменить это, чтобы я мог получить результат, который я ищу.
Спасибо
Комментарии:
1.
How do I reverse pivot this so I can achieve the output I'm looking for.
— можете ли вы визуализировать это, показав пример ожидаемого результата здесь!2. Я did…it это третий кодовый блок.
3. теперь я вижу — это было непонятно для меня
4. можете ли вы уточнить, как вы считаете ошибки — на основе вашего примера я бы сказал, что у col1 есть 1 ошибка, а у col2 есть 1 ошибка, но в окончательном выводе вы показываете 0 для обоих?
5. это означает, что на основе вашего примера (блок 2) в вашем ожидаемом выводе (блок 3) количество для cnt_col1 должно быть 1, а для cnt_col2 должно быть 1 — даже если вы можете подумать, что это не важно для вашего вопроса — но важно — представить все ясно и чисто. : o) таким образом, мы можем эффективно помочь
Ответ №1:
Как мне изменить это, чтобы я мог получить результат, который я ищу.
Предполагая, что у вас есть таблица `данные`
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
Ниже приведен стандартный SQL BigQuery, который делает именно это
#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)),
— что можно сделать вручную, или вы можете просто написать простой скрипт для генерации этих строк (или целого запроса)
Комментарии:
1. я рад, что это помогло! любите BigQuery, а также любите SO, поскольку это дает возможность передавать / делиться знаниями и помогать людям: o)
Ответ №2:
Что касается «сравнения 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 (еще не законченный, я надеюсь, что моя компания позволит мне открыть исходный код после завершения), который выполнит следующее:
- подсчитайте строки для некоторых «сегментов» (групп строк, столбец которых с хорошим распределением имеет одинаковую контрольную сумму по модулю большого числа) и сравните результаты (потому что нет необходимости проверять всю таблицу, если количество строк не совпадает).
- визуально показывает различия, если количество не совпадает
- используйте метод bucket / rows некоторые другие «сегменты / столбцы», чтобы выполнить некоторые контрольные суммы аналогичным образом, как показано в примере выше. И сравните все эти контрольные суммы вместе.
- визуально показывает различия, если контрольные суммы не совпадают
Редактировать 11.03.2017: сценарий завершен и его можно найти по адресу: https://github.com/bolcom/hive_compared_bq
Комментарии:
1. Sourygna, это блестящая стратегия, и я хотел бы посмотреть, как вы реализуете ее, когда используете свой код на Python. Однако мои сотрудники сказали, что я должен определить те столбцы, которые не совпадают, чтобы определить, произошел ли у нас сбой преобразования. Для проверки строк это звучит убедительно. Спасибо за предложение.
2. Да, идея пункта 3) состоит в том, чтобы иметь возможность видеть как строки, так И столбцы, которые не совпадают. Я делю на «группы столбцов», чтобы уменьшить количество промежуточных результатов (контрольных сумм). Это также означает, что когда я покажу различия в пункте 4), я смогу показать конечному пользователю только некоторые группы столбцов, которые терпят неудачу (группа будет состоять примерно из 5 столбцов). Давайте посмотрим, смогу ли я закончить в ближайшие несколько дней и смогу ли я показать вам какие-то результаты.
3. Вот проект скрипта Python, о котором я упоминал ранее: github.com/bolcom/hive_compared_bq