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

时间:2016-05-14 09:35:54

标签: sql postgresql common-table-expression dml

我有一个名为listens的表,其中包含PRIMARYKEY(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,那么,所有旧记录都是比 max-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);

任何解决方案?

2 个答案:

答案 0 :(得分:4)

我认为你所需要的只是使它成为一个共同相关的子查询:

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是一个列的可怕名称,尤其是一个不包含时间戳值的列。一个原因是因为它也是一个关键字,但更重要的是它没有记录该列包含的内容。注册时间戳?到期时间戳?最后一个活跃的时间戳?功能

答案 1 :(得分:1)

或者,您可以使用EXISTS()

来避免使用MAX()
DELETE FROM listens d
WHERE EXISTS (
        SELECT * FROM listens x
        WHERE x.uid = d.uid
        AND x.timestamp >= d.timestamp + 10000 
        );  

BTW:timestamp是列的丑陋名称,因为它也是一个类型名。