BigQuery: удаление дубликатов в секционированной таблице - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть таблица BQ, которая разделена по времени вставки.Я пытаюсь удалить дубликаты из таблицы.Это истинные дубликаты: для 2-х одинаковых строк все столбцы равны - конечно, полезно иметь уникальный ключ: - (

Сначала я попытался выполнить запрос SELECT, чтобы перечислить дубликаты и удалить их:

SELECT
    * EXCEPT(row_number)
FROM (
    SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY id_column) row_number
    FROM
    `mytable`)
WHERE
    row_number = 1

Это приводит к уникальным строкам, но создает новую таблицу, которая не включает данные раздела - так что не очень хорошо.

Я видел этот ответ здесь , которыйутверждает, что единственный способ сохранить разделы - это просмотреть их один за другим с помощью вышеуказанного запроса и сохранить в определенном целевом разделе таблицы.

Что я действительно хочу сделать, так это использовать DML DELETE чтобы удалить дублирующиеся строки на месте. Я попробовал что-то похожее на то, что этот ответ предложил :

DELETE
FROM `mytable` AS d
WHERE (SELECT ROW_NUMBER() OVER (PARTITION BY id_column)
   FROM `mytable ` AS d2
   WHERE d.id = d2.id) > 1;

Но принятый ответ не работает и приводит к ошибке BQ:

Error: Correlated subqueries that reference other tables are not supported unless they can be de-correlated, such as by transforming them into an efficient JOIN

Было бы здорово, если бы кто-нибудь мог предложить более простой (DML или иной) способ решения этой проблемы, поэтому мне не нужно будет циклически перебирать все разделы по отдельности.

1 Ответ

0 голосов
/ 06 декабря 2018

Вроде хак, но вы можете использовать оператор MERGE для удаления всего содержимого таблицы и повторной вставки только отдельных строк атомарно.Вот пример:

-- Create a table with some duplicate rows
CREATE TABLE dataset.PartitionedTable
PARTITION BY date AS
SELECT x, CONCAT('foo', CAST(x AS STRING)) AS y, DATE_SUB(CURRENT_DATE(), INTERVAL x DAY) AS date
FROM UNNEST(GENERATE_ARRAY(1, 10)) AS x, UNNEST(GENERATE_ARRAY(1, 10));

Теперь для MERGE части:

-- Execute a MERGE statement where all original rows are deleted,
-- then replaced with new, deduplicated rows:
MERGE dataset.PartitionedTable AS t1
USING (SELECT DISTINCT * FROM dataset.PartitionedTable) AS t2
ON FALSE
WHEN NOT MATCHED BY TARGET THEN INSERT ROW
WHEN NOT MATCHED BY SOURCE THEN DELETE
...