删除Postgresql中具有指定参数但最新的所有行

时间:2015-09-14 18:56:47

标签: sql postgresql sql-delete

我有一个哈希表:

CREATE TABLE hash_table ( hash_id bigserial, 
user_name varchar(80),
 hash varchar(80), 
exp_time bigint,
 PRIMARY KEY (hash_id));


INSERT INTO hash_table (hash_id, user_name, exp_time) VALUES
(1, 'one',   10),
(2, 'two',   20),
(3, 'three', 31),
(4, 'three', 32),
(5, 'three', 33),
(6, 'three', 33),
(7, 'three', 35),
(8, 'three', 36),
(9, 'two',   40),
(10, 'two',   50),
(11, 'one',   60),
(12, 'three', 70);

exp_time - 哈希的到期时间。行创建时exp_time = now() + delta_time

我需要一个结果:

(1, 'one',   10),
(2, 'two',   20),
(7, 'three', 35),
(8, 'three', 36),
(9, 'two',   40),
(10, 'two',   50),
(11, 'one',   60),
(12, 'three', 70);

它包含许多user_name-hash对。 user_name可能会占用很多时间。

如何删除所有行但是(几个,例如10个)最新指定的user_name?

我发现了this解决方案(对于mySQL但我希望它有效)但它会删除所有其他user_names

DELETE FROM `hash_table`
WHERE user_name NOT IN (
  SELECT user_name
  FROM (
    SELECT user_name
    FROM `hash_table`
    ORDER BY exp_time DESC
    LIMIT 10 -- keep this many records
  )
);

3 个答案:

答案 0 :(得分:1)

这将为每个user_name保留3条最新记录:

DELETE FROM hash_table h
USING
(
  SELECT
    user_name,
    exp_time,
    row_number() OVER (PARTITION BY user_name ORDER BY exp_time DESC) AS r
  FROM
    hash_table
) AS s
WHERE
  h.user_name = s.user_name
  AND h.exp_time<s.exp_time
  AND s.r=3

答案 1 :(得分:0)

您可以使用row_number按降序排列基于exp_time的用户行。然后从表中删除包含10个以上条目的用户行。

Fiddle with sample data

 delete from hash_table as h 
 using
 (
 SELECT user_name, exp_time,
 row_number() over(partition by user_name order by exp_time desc) as rn
 FROM hash_table
 ) as t
 where h.user_name = t.user_name and h.exp_time <= t.exp_time and t.rn > 10;

答案 2 :(得分:0)

DELETE FROM hash_table WHERE hash_id NOT IN (SELECT hash_id FROM hash_table WHERE user_name = 'three' ORDER BY exp_time DESC LIMIT 3) AND user_name = 'three';

我自己回答:查询仅计算所需user_name的行,而不是所有user_name的行。