根据年龄、状态和PostgreSQL中相关行的存在性删除行

6l7fqoea  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(3)|浏览(120)
create table the_table (
  id integer, root_id integer, parent_id integer, status text, ts timestamp, comment text);
insert into the_table values
(1, null, null, 'COMPLETE', now()-'92d'::interval, '>90 days old, complete, standalone'),
(2, null, null, 'COMPLETE', now()-'92d'::interval, '>90 days old, complete, root of 3,4'),
(3, 2,    null, 'COMPLETE', now()-'92d'::interval, '>90 days old, complete, child of 2, parent of 4'),
(4, 2,    3,    'OPEN',     now()-'92d'::interval, '>90 days old, open, child of 2,3'),
(5, null, null, 'COMPLETE', now()-'92d'::interval, '>90 days old, complete, root of 6,7'),
(6, 5,    null, 'COMPLETE', now()-'92d'::interval, '>90 days old, complete, child of 5, parent of 4'),
(7, 5,    6,    'COMPLETE', now()-'10d'::interval, '<=90 days old, complete, child of 5,6' )

字符串
从表中删除所有记录,

  • 超过90天
  • 处于COMPLETE状态。

如果一行有root_idparent_id,并且是OPEN,那么root_idparent_id行不应该被删除。
在上表中,应删除带有id=1的行。
id=2id=3COMPLETE,并且超过90天,但由于id=4OPEN,并且具有root_id=2parent_id=3,因此不应删除这三行(id in (2,3,4))。
id=5id=6id=7都是COMPLETE,但id=7不超过90天,并且有root_id=5parent_id=6,因此这三行(id=5id=6id=7)不应删除。
我尝试了多种内部查询的方法,但我无法为这种情况编写查询。
DB<>Fiddle

zvokhttg

zvokhttg1#

1.您希望仅删除COMPLETE * 且 * >90天的行。
1.如果某行满足1.删除条件,但它是某行的子行、父行或根行,而该行由于仍为OPEN或太年轻而无法删除,则您不希望删除任何链接的行。对称:锁定父行锁定子行,锁定子行锁定父行。

DELETE FROM the_table t1
WHERE 'COMPLETE'=status AND now()-ts > '90d'::interval
AND NOT EXISTS (SELECT FROM the_table AS t2
                WHERE (   t1.id IN(t2.root_id,t2.parent_id)
                       OR t2.id IN(t1.root_id,t1.parent_id) )
                  AND (   'OPEN'=t2.status
                       OR now()-t2.ts <= '90d'::interval    )  )
RETURNING *;

字符串
| ID|根ID|父ID|地位|ts|评论|
| --|--|--|--|--|--|
| 1 |* 空 | 空 *| 完成|2023-08-09 11:14:25.445328|>90天,完整,独立|
我在this db<>fiddle demo中添加了更多的测试用例。最后有一个用例需要澄清:一个可移动的父节点,有两个子节点,一个不可移动,一个可移动。如果您允许删除可移动的子节点,而父节点与不可移动的子节点保持在一起,那么这可以工作。如果您希望保留整个图/族,直到所有节点/成员都可移动,你需要一个递归CTE或者routine来遍历这个图。

ghhaqwfi

ghhaqwfi2#

将您的需求转换为SQL,我得到

DELETE FROM tab
WHERE status = 'COMPLETE'
  AND timestamp < current_timestamp - INTERVAL '90 days'
  AND NOT EXISTS (SELECT 1 FROM tab AS t2
                  WHERE t2.status = 'OPEN'
                    AND (tab.id = t2.root_id OR tab.id = t2.parent_id)
                 );

字符串

rqenqsqc

rqenqsqc3#

一步一步-首先识别记录id-s,这些记录是具有“OPEN”状态的记录的父记录或根记录,并将它们存储在t CTE中,然后删除那些“COMPLETE”、超过90天且其id不在t中的记录。

with t (id) as 
(
 select unnest(array[root_id, parent_id])
 from the_table 
 where status = 'OPEN' 
   and (root_id is not null or parent_id is not null)
)
delete from the_table
where status = 'COMPLETE'
  and ts = 'older than 90 days'
  and id not in (select id from t);

字符串
DB-fiddle demo

相关问题