在table中只保留3个最高的正面和负面记录

Retain only 3 highest positive and negative records in a table

我是数据库和 postgres 的新手。 我有一个名为 names 的 table,它有 2 列 name 和 value,每 x 秒更新一次新的名称值对。我的要求是在任何时间点只保留 3 个正值和 3 个负值,并在每次 table 更新期间删除其余行。 我使用以下查询删除旧行并保留按值排序的 3 个正值和 3 个负值。

delete from names
using (select  *,
row_number() over (partition by value > 0, value < 0 order by value desc) as rn
from names ) w
where w.rn >=3

我对在分区语句中使用 value > 0 这样的条件表示怀疑。这种方法正确吗?

例如,

A table 在删除之前像这样:

name  | value 
--------------
test  |  10 
test1 |  11
test1 |  12
test1 |  13
test4 |  -1
test4 |  -2

删除后我的 table 应如下所示:

name  | value 
--------------
test1 |  13
test1 |  12
test1 |  11
test4 |  -1 
test4 |  -2

demo:db<>fiddle

这通常按预期工作:value > 0 将值聚类到所有数字 > 0 和所有数字 <= 0。ORDER BY value 按预期对这两个组进行排序。

所以,我唯一要改变的是:

row_number() over (partition by value >= 0 order by value desc) 
  1. 删除:, value < 0(因为:为什么要将正值分为负值和其他?正值组中没有任何负数,反之亦然。)
  2. 更改:value > 0value >= 0 以尽可能长时间地忽略 0

对于删除:如果要保留每个方向的前3个值:

  1. 您应该将 w.rn >= 3 更改为 w.rn > 3(它也保留第 3 个元素)
  2. 您需要将子查询与 table 条记录连接起来。在实际情况下,您应该为此使用 id 列。在您的示例中,您可以采用值列:where n.value = w.value AND w.rn > 3

所以,最后:

delete from names n
using (select  *,
row_number() over (partition by value >= 0 order by value desc) as rn
from names ) w
where n.value = w.value AND w.rn > 3

如果删除其他行不是硬性要求,您可以 select 只删除您感兴趣的行:

WITH largest AS (
  SELECT name, value
    FROM names
   ORDER BY value DESC
   LIMIT 3),
     smallest AS (
  SELECT name, value
    FROM names
   ORDER BY value ASC
   LIMIT 3)
SELECT * FROM largest
UNION
SELECT * FROM smallest
ORDER BY value DESC