在 postgresql 的单个查询中使用 WITH + DELETE 子句

Posted

技术标签:

【中文标题】在 postgresql 的单个查询中使用 WITH + DELETE 子句【英文标题】:Using WITH + DELETE clause in a single query in postgresql 【发布时间】:2016-09-10 12:55:17 【问题描述】:

我有以下表结构,对于一个名为listens 的表,PRIMARYKEY on (uid,timestamp)

     Column     |            Type             |                      Modifiers                       
----------------+-----------------------------+------------------------------------------------------    
 id             | integer                     | not null default nextval('listens_id_seq'::regclass)
 uid            | character varying           | not null
 date           | timestamp without time zone | 
 timestamp      | integer                     | not null
 artist_msid    | uuid                        | 
 album_msid     | uuid                        | 
 recording_msid | uuid                        | 
 json           | character varying           | 

我需要删除特定用户 (uid) 的所有条目,这些条目早于最大时间戳,例如 max 为 123456789(以秒为单位),delta 为 100000,然后,所有记录都较旧大于 ma​​x-100000

当表包含单个用户时,我设法创建了一个查询,但我无法将其制定为适用于数据库中的每个用户。需要对数据库中的每个用户都执行此操作。

WITH max_table as (
    SELECT max(timestamp) - 10000 as max 
    FROM listens 
    GROUP BY uid) 
DELETE FROM listens 
WHERE timestamp < (SELECT max FROM max_table);

有什么解决办法吗?

【问题讨论】:

您想关联单个最大值还是每个用户的最大值? 【参考方案1】:

我认为您所需要的只是将其设为一个相关的子查询:

WITH max_table as (
    SELECT uid, max(timestamp) - 10000 as mx
    FROM listens 
    GROUP BY uid
) 
DELETE FROM listens 
WHERE timestamp < (SELECT mx
                   FROM max_table 
                   where max_table.uid = listens.uid);

顺便说一句:timestamp 是一个可怕的列名称,尤其是不包含时间戳值的列。一个原因是因为它也是一个关键字,但更重要的是它没有记录该列包含的内容。注册时间戳?过期时间戳?最后一个活动时间戳?

【讨论】:

timestamp 包含正在插入的记录的侦听时间戳(实际时间戳)。数据是每个用户的监听数据。【参考方案2】:

或者,您可以通过使用 EXISTS() 来避免 MAX()

DELETE FROM listens d
WHERE EXISTS (
        SELECT * FROM listens x
        WHERE x.uid = d.uid
        AND x.timestamp >= d.timestamp + 10000 
        );  

顺便说一句:timestamp 是一个难看的列名,因为它也是一个类型名。

【讨论】:

以上是关于在 postgresql 的单个查询中使用 WITH + DELETE 子句的主要内容,如果未能解决你的问题,请参考以下文章

用于获取存储在单个表中的 n 级父子关系的 Postgresql 查询

单个查询中的 Postgresql 多个连接,其中连接的外键不存在于所有表中

PostgreSQL - 如何在单个查询中获取列的最小值和最大值以及与它们关联的行?

Postgresql:FROM 中的子查询必须有别名 - 具有多个连接

使用 SQLAlchemy 从 PostgreSQL 行对象中获取单个值

如何在 Ruby 中使用 Where 子句 (PostgreSQL) 中的变量编写查询