【发布时间】:2022-11-14 01:04:52
【问题描述】:
我的表结构大致如in this post所述:
| name | processed | processing | updated | ref_time |
|---|---|---|---|---|
| abc | t | f | 27794395 | 27794160 |
| def | t | f | 27794395 | 27793440 |
| ghi | t | f | 27794395 | 27793440 |
| jkl | f | f | 27794395 | 27794160 |
| mno | t | f | 27794395 | 27793440 |
| pqr | f | t | 27794395 | 27794160 |
我已经基于这个表结构创建了一个dbfiddle(更多内容见下文),因此无需创建您自己的。
基于this answer,我得到了一个ref_time值的列表,用作从status_table删除“旧”条目的基础:
with
ref as (
select ref_time
from status_table
group by ref_time
having bool_and(processed)
order by ref_time desc
offset 1
)
delete from status_table s
using ref r
where s.ref_time = r.ref_time
但是现在我想对我用作offset 的内容更加复杂...我理想情况下希望保留处理所有记录的最新ref_time(根据上面的示例,offset 是@ 987654333@),但是最近的两个ref_time 其中第二个 ref_time 的关联记录比第一个多(即 offset 需要是 2 才能跳过最近的两个 ref_time)。
我认为以下查询(基于this answer)将有助于完成此任务,因为它根据ref_time 计算processed 记录的总数:
select ref_time,
count(*) cnt_total,
count(*) filter(where processed) cnt_processed,
round(avg(processed::int),2) ratio_processed
from status_table
group by ref_time
order by ratio_processed desc, ref_time desc;
所以在 this dbfiddle 中,我需要保留 ref_time=27794160(而不是像示例中那样将其包含在删除列表中),因为尽管它是第二个,但它的 cnt_total 也比第一个高。
一般来说,规则是我希望将所有 ref_time 保留到(但不包括)与之前(或更少)具有相同 cnt_total 的 ref_time。
【问题讨论】:
-
你可以编辑倒数第二段,让它更明显你已经包含了一个 dbfiddle 吗?我只是在没有意识到的情况下离开并创建了自己的。
-
在您提供的最后一个示例中,您有 4 个 ref_time 组(27794170、27794160、27793450、27793440)。您的目标是删除 27794170 之后的所有内容,除非之前的记录具有更高的计数(在本例中为 27794160)。如果 27793450 的计数高于 27794160,会发生什么情况?
-
@JimJimson 您问“如果 27793450 的计数高于 27794160 会怎样?”。根据最后一段中的规则,如果是这种情况,那么我们应该保留 27793450... 但请记住,由于
delete查询中的having bool_and(processed),我们只有在所有记录都是 @987654349 时才会删除@... 在此示例中,27793450 并非如此...因此,无论它的计数是否高于 27794160,我们都会保留它。
标签: sql postgresql aggregate-functions sql-delete gaps-and-islands