I need to keep the last 5 search results of a user in a table.
I wrote a script to remove other rows, but it didn't work:
DELETE FROM
SELECT
ROW_NUMBER () OVER (ORDER BY search_time DESC) AS row_number;
FROM
history_user
WHERE
user_id = 188
WHERE row_number>5
What did I do wrong?
Proper syntax as detailed in the manual:
DELETE FROM history_user h
USING (
SELECT pk_id, row_number() OVER (ORDER BY search_time DESC) AS rn;
FROM history_user
WHERE user_id = 188
) sub
WHERE sub.rn > 5
AND h.pk_id = sub.pk_id;
Where pk_id
is any (combination of) column(s) that is unique. Might be user_id
, search_time
in your case - or, more conveniently, a surrogate primary key.
For just a single user_id
you can simplify to:
DELETE FROM history_user h
USING (
SELECT pk_id
FROM history_user
WHERE user_id = 188
ORDER BY search_time DESC
OFFSET 5
) sub
WHERE h.pk_id = sub.pk_id;
On the other hand, to deal with multiple users at once, you need to add PARTITION BY
to your window function:
DELETE FROM history_user h
USING (
SELECT pk_id, row_number() OVER (PARTITION BY user_id
ORDER BY search_time DESC) AS rn;
FROM history_user
) sub
WHERE sub.rn > 5
AND h.pk_id = sub.pk_id;