#sql #google-bigquery #union-all
#sql #google-bigquery #объединение всех
Вопрос:
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
не выдает ошибку, потому что обе таблицы имеют одинаковое количество столбцов (по 3 в каждой). Однако я получаю неверный вывод данных, потому что столбцы не совпадают. Вместо того, чтобы выводить новую таблицу с 4 столбцами name
, age
, speed
, strength
union all
с правильными значениями nulls для пропущенных значений (что, вероятно, было бы предпочтительнее), в, , сохраняет 3 столбца из верхней строки.
Есть ли хороший способ определить, что столбцы не совпадают, вместо того, чтобы запрос автоматически возвращал неверные данные? Есть ли какой-либо способ вернуть ошибку, возможно, в отличие от успешной таблицы? Я не уверен, как проверить в SQL, что столбцы в 2 таблицах совпадают.
Редактировать: в этом примере ясно видно, что столбцы не совпадают, однако в наших данных у нас более 100 столбцов, и мы хотим избежать ситуации, когда мы допустим ошибку при объединении ВСЕХ
Комментарии:
1. вам всегда нужно указывать имя столбца в случае использования объединения всех, а также порядок столбцов должен быть одинаковым для всех наборов данных при использовании объединения всех
2. Да, я знаю, что порядок столбцов должен быть одинаковым при использовании
union all
. Мой вопрос заключается в том, существует ли способ вычислить, что имена столбцов порядки фактически одинаковы.3. Суть в том, что не используйте
*
в качестве проекции при выполненииUNION ALL
, а явно перечисляйте столбцы.4. Я понимаю наилучшую практику. Я просто спрашиваю, возможно ли поймать / обработать ошибку в том случае, если имена столбцов не совпадают
5. вы хотите сделать это во «время выполнения» или «во время разработки»? другими словами — это нормально, просто сначала сравнить схему и, если все кошерно, чем в отдельном запросе, запустить ваш union all stuff? — о, хорошо — это именно то, что ты только что ответил
Ответ №1:
Ниже приведен стандартный SQL BigQuery и функция использования сценариев 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
Ответ №2:
После сохранения table1
и table2
в виде 2 таблиц в наборе данных в BigQuery я затем использовал метаданные с помощью 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
возвращает информацию, включая имена столбцов и их расположение. Затем я могу объединить эти 2 таблицы вместе, чтобы проверить, совпадают ли имена…