I have a postgresql (v8.4) table with login id and timestamps, and I want to create a batch file that will be run periodically to remove entries when the same id has more than X number of entries in the table. Also, the number of entries to keep is stored in a separate table and can be different for each id.
The pertinent columns of the two tables:
CREATE TABLE user_profile (
id varchar(256) PRIMARY KEY,
history_count integer
)
CREATE TABLE access_history (
id varchar(256),
login_time timestamp
)
The solution I'm contemplating involves 3 SQL commands:
get all login ids with excess entry counts
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;
loop through each entry from the above query and get the time stamp for the last entry
SELECT login_time FROM access_history WHERE id = 'user id' ORDER BY login_time DESC OFFSET 200 LIMIT 1;
delete entries older then the time stamp retrieved from #2
DELETE 开发者_JAVA百科from access_history WHERE id = 'user id' AND login_time <= '2011-06-06 10:22:29.604156'
I am admittedly a novice in SQL, but feel like there must a more efficient way of performing this operation.
thanks in advance
with cte
as
(
select id, row_number() over (order by login_time desc) RowNumber
from access_history
)
delete cte
where RowNumber > 200
Replace 200 with the max number of logins you want to keep in history for each user.
[EDIT]
As a_horse_with_no_name mentioned, cte with delete is not supported by 8.4.
You could use delete with a subquery like this.
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
)
精彩评论