在表中仅保留3个最高的正负记录

时间:2019-09-26 04:25:48

标签: postgresql postgresql-9.3

我对数据库和Postgres还是陌生的。 我有一个名为名称的表,该表具有2列名称和值,每x秒用新的名称值对更新。我的要求是在任何时间点仅保留3个正值和3个负值,并在每次表更新期间删除其余行。 我使用以下查询删除旧行,并保留按值排序的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

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

例如

像这样删除之前的表:

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

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

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

2 个答案:

答案 0 :(得分:1)

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 > 0更改为value >= 0,以便尽可能长地忽略0

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

  1. 您应该将w.rn >= 3更改为w.rn > 3(它也保留了第3个元素)
  2. 您需要将子查询与表记录连接。在实际情况下,您应该使用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

答案 1 :(得分:0)

如果不是很难删除其他行,则可以只选择您感兴趣的行:

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