在 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,然后,所有记录都较旧大于 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);
有什么解决办法吗?
【问题讨论】:
您想关联单个最大值还是每个用户的最大值? 【参考方案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 中的子查询必须有别名 - 具有多个连接