两个列上的BigQuery DeDuplication作为唯一键

时间:2016-07-18 21:46:36

标签: sql google-bigquery gcp

我们虔诚地使用BigQuery并且有两个表基本上由不同的进程并行更新。我遇到的问题是,我们没有表的唯一标识符,目标是尽可能将两个表合并为零重复。唯一标识符是两列组合。

我尝试过各种基于MySQL的查询,但似乎没有一个在BigQuery中运行。所以我在这里张贴一些帮助。 :)

步骤1.复制"清洁"表进入新的合并表。

步骤2.查询"脏" (旧)表并插入任何缺失的条目。

查询尝试1:

SELECT
  COUNT(c.*)
FROM
  [flash-student-96619:device_data.device_datav3_20160530] AS old
WHERE NOT EXISTS (
  SELECT
    1
  FROM
    [flash-student-96619:device_data_v7_merged.20160530] AS new
  WHERE
    new.dsn = old.dsn
    AND new.timestamp = old.timestamp 
)

错误:错误:6.1 - 10.65。一次只能执行一个查询。

查询尝试2:

SELECT
  *
FROM
  [flash-student-96619:device_data.device_datav3_20160530]
WHERE
  (dsn, timestamp) NOT IN (
  SELECT
    dsn,
    timestamp
  FROM
    [flash-student-96619:device_data_v7_merged.20160530] 
  )

错误:遇到" "" ",""在第6行,第7栏。期待:")" ...

老实说,如果我能在一个查询中做到这一点,我会很高兴。我需要从两个表中获取,并使用唯一数据创建一个新表。

有任何帮助吗?

2 个答案:

答案 0 :(得分:3)

下面的内容应该有效

SELECT * 
FROM (
  SELECT *,
    ROW_NUMBER() OVER(PARTITION BY dsn, timestamp) AS dup
  FROM
    [flash-student-96619:device_data.device_datav3_20160530],
    [flash-student-96619:device_data_v7_merged.20160530] 
) 
WHERE dup = 1  

我建议在外部SELECT中使用显式字段列表而不是*,这样就可以省略实际输出中的dup

答案 1 :(得分:1)

有点晚了,但我想指出原始查询使用standard SQL进行微小修改(取消选中“显示选项”下的“使用旧版SQL”框)。我只需将new更改为其他内容,因为这是一个保留关键字。例如,此查询有效:

WITH OldData AS (
  SELECT
    x AS dsn,
    TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL x HOUR) AS timestamp
  FROM UNNEST([1, 2, 3, 4]) AS x),
NewData AS (
  SELECT
    x AS dsn,
    TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL x HOUR) AS timestamp
  FROM UNNEST([5, 2, 1, 6]) AS x)
SELECT
  COUNT(*)
FROM OldData oldData
WHERE NOT EXISTS (
  SELECT 1
  FROM NewData newData
  WHERE
    newData.dsn = oldData.dsn
    AND newData.timestamp = oldData.timestamp
);
+-----+
| f0_ |
+-----+
|   2 |
+-----+

关于你的第二次尝试,你可以这样做:

WITH OldData AS (
  SELECT
    x AS dsn,
    TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL x HOUR) AS timestamp
  FROM UNNEST([1, 2, 3, 4]) AS x),
NewData AS (
  SELECT
    x AS dsn,
    TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL x HOUR) AS timestamp
  FROM UNNEST([5, 2, 1, 6]) AS x)
SELECT
  *
FROM OldData
WHERE
  STRUCT(dsn, timestamp) NOT IN (
  SELECT AS STRUCT
    dsn,
    timestamp
  FROM NewData);
+-----+---------------------+
| dsn |      timestamp      |
+-----+---------------------+
|   3 | 2016-07-21 11:54:08 |
|   4 | 2016-07-21 10:54:08 |
+-----+---------------------+