BigQuery:从表连接引起的子选择中删除记录

Posted

技术标签:

【中文标题】BigQuery:从表连接引起的子选择中删除记录【英文标题】:BigQuery: Delete records from subselect caused by table join 【发布时间】:2019-03-19 17:26:57 【问题描述】:

问题

所以我收集了一些进行连接的行,我需要通过查询删除这些行。有谁知道如何形成删除查询?我知道这听起来很容易,但找不到方法。

代码

SELECT * FROM (
        SELECT 
           entity_key, min(actual_posting_time) as min_time
        FROM 
            myTable
        WHERE 
            _PARTITIONTIME BETWEEN TIMESTAMP("2018-12-01") AND TIMESTAMP("2018-12-04")
        GROUP BY
            entity_key
        HAVING
            COUNT(*) >= 2 
        )t1
    LEFT JOIN
        (
        SELECT entity_key, actual_posting_time
        FROM 
            myTable 
        WHERE _PARTITIONTIME BETWEEN TIMESTAMP("2018-12-01") AND TIMESTAMP("2018-12-04")
        ) t2
    ON t1.entity_key  = t2.entity_key
  AND min_time <> t2.actual_posting_time )

因此,我想从上面的子选择中删除 myTable 中的每条记录。任何建议都非常感谢。

【问题讨论】:

哪个子查询?你有两个。 @RyanWilson 这次加入的结果是我有兴趣删除的结果。 A DELETE FROM TABLE WHERE entity_key IN (Your example query) 应该这样做,除非您将最外面的查询更改为仅选择 entity_key 而不是 * 是的,我在 SQL-Server 中工作,所以对于 bigquery 来说,有些东西似乎不存在,我想你可以按照你说的为每条记录创建唯一的列值,我可以如果这是您的决定,请为您提供一些帮助。 是的合并命令确实插入、更新和删除,这非常酷。我建议你仔细检查一下。 【参考方案1】:

据我了解查询,您希望保留具有相同 entity_key 的行的最旧记录。在这种情况下,您可以只 CONCAT 两个字段,如下所示:

DELETE * FROM myTable 
WHERE CONCAT(CAST(entity_key as string), '_', CAST(actual_posting_time as string)) 
NOT IN (
    SELECT 
       CONCAT(CAST(entity_key as string), '_', CAST(min(actual_posting_time) as min_time)
    FROM 
        myTable
    WHERE 
        _PARTITIONTIME BETWEEN TIMESTAMP("2018-12-01") AND TIMESTAMP("2018-12-04")
        AND entity_key IS NOT NULL
    GROUP BY
        entity_key
    HAVING
        COUNT(*) >= 2 
)

子查询中 WHERE 子句的第二个条件是由于 NOT IN 与标准 SQL 的语义,如 here 所述。使用一些公共数据集,您可以看到使用 select 命令将删除的结果:

#standardSQL
SELECT * 
FROM `bigquery-public-data.austin_311.311_service_requests` 
WHERE CONCAT(CAST(complaint_type as string), '_',CAST(status_change_date as string)) NOT IN (
    SELECT CONCAT(CAST(complaint_type as string), '_',CAST(min(status_change_date) as string))
    FROM `bigquery-public-data.austin_311.311_service_requests`
    WHERE complaint_type is not null
    GROUP BY complaint_type
)

实现此目的的另一种方法是使用EXISTS,如下所示:

#standardSQL
WITH t1 AS (
  SELECT complaint_type, MIN(status_change_date) AS min_date
  FROM `bigquery-public-data.austin_311.311_service_requests`
  GROUP BY complaint_type )
SELECT *
FROM `bigquery-public-data.austin_311.311_service_requests` AS t2
WHERE NOT EXISTS (
  SELECT 1
  FROM t1
  WHERE t1.complaint_type = t2.complaint_type
    AND t1.min_date = t2.status_change_date 
)

请注意,对于这个公共表,结果会略有不同,因为有status_change_dateNULL 的行。 NOT IN 不会删除这些,但NOT EXISTS 会删除。

【讨论】:

以上是关于BigQuery:从表连接引起的子选择中删除记录的主要内容,如果未能解决你的问题,请参考以下文章

从 BigQuery 中删除重复记录

从表内连接中删除 - ORA-00933:SQL 命令未正确结束

如何从表中删除重复记录? [复制]

从表中删除所有记录 - doCMD.RunSQL

从表一的比较更新表二,bigQuery

使用复选框从表中删除记录[重复]