从postgresql表中删除旧的时间戳登录历史记录行

从postgresql表中删除旧的时间戳登录历史记录行,sql,postgresql,Sql,Postgresql,我有一个带有登录id和时间戳的postgresql(v8.4)表,我想创建一个批处理文件,当同一id表中的条目数超过X时,该批处理文件将定期运行以删除条目。此外,要保留的条目数存储在一个单独的表中,每个id的条目数可能不同 两个表的相关列: CREATE TABLE user_profile ( id varchar(256) PRIMARY KEY, history_count integer ) CREATE TABLE access_history ( id varchar(

我有一个带有登录id和时间戳的postgresql(v8.4)表,我想创建一个批处理文件,当同一id表中的条目数超过X时,该批处理文件将定期运行以删除条目。此外,要保留的条目数存储在一个单独的表中,每个id的条目数可能不同

两个表的相关列:

CREATE TABLE user_profile (
  id varchar(256) PRIMARY KEY,
  history_count integer
)

CREATE TABLE access_history (
  id varchar(256),
  login_time timestamp
)
我正在考虑的解决方案涉及3个SQL命令:

  • 获取具有多余条目计数的所有登录ID

    SELECT access_history.id, count(*), user_profile.history_count
      FROM d_access_history 
      LEFT JOIN d_user_profile 
      ON access_history.id = user_profile.id 
      GROUP BY access_history.id, user_profile.history_count
      HAVING count(*) > user_profile.history_count;
    
  • 循环遍历上述查询中的每个条目,并获取最后一个条目的时间戳

    SELECT login_time 
      FROM access_history 
      WHERE id = 'user id'
      ORDER BY login_time DESC 
      OFFSET 200 LIMIT 1;
    
  • 删除早于从#2中检索到的时间戳的条目

    从访问历史记录中删除
    其中id='user id'
    和登录时间
    将200替换为每个用户希望保留在历史记录中的最大登录次数

    [编辑]

    正如前面提到的没有名字的马一样,8.4不支持带删除的cte。
    您可以将delete与这样的子查询一起使用

    delete access_history
    where id in
    (
        select id
        from
        (
            select id, row_number() over (order by login_time desc) RowNumber
            from access_history
        ) tt
        where RowNumber > 200
    )
    

    这将需要尚未发布的9.1版。@一匹没有名字的马-你确定吗?我可以看到8.4中提供了窗口功能:。是,提供了窗口功能。但是,只有在9.1(称为可写CTE)中才支持将CTE与DELETE语句一起使用,顺便说一句:您的解决方案是一个不错的主意,如果您将CTE更改为subselect,它应该可以工作。
    with cte
    as
    (
        select id, row_number() over (order by login_time desc) RowNumber
        from access_history
    )
    delete cte
    where RowNumber > 200
    
    delete access_history
    where id in
    (
        select id
        from
        (
            select id, row_number() over (order by login_time desc) RowNumber
            from access_history
        ) tt
        where RowNumber > 200
    )