I have a table in which I need to keep the total number of rows within 50,000. This table includes an Id field (id is auto incremental).
How can I check if max(id) - min(id) > 50,000, then delete the earlier rows?
DELETE FROM news WHERE if (max(id) - min(id) > 50000)
This query will delete all the rows if max(id) - min(id) > 50000, what is the correct way? Ideally I need a one line command, excuse in SSH method. thanks.
DELETE d
FROM news AS d
JOIN
( SELECT MAX(id)-50000 AS lim
FROM news
) AS m
ON d.id < m.lim ;
The above will not leave exactly 50K rows of course, as there may be gaps in the id sequence. But I guess this is expected and not a problem. If you really want to leave exactly 50K rows, any statement will probably be less efficient. You can try this one:
DELETE d
FROM news AS d
JOIN
( SELECT id AS lim
FROM news
ORDER BY id DESC
LIMIT 1 OFFSET 50000
) AS m
ON d.id <= m.lim ;
Delete from news where id < max(id)-50000
DELETE FROM news
WHERE id NOT IN (SELECT id FROM news ORDER BY id DESC LIMIT 50000)
Related
I have a condition, where in Audit logs, if the records exceeds 100k, then delete the previous old records, I dont want to delete all the 100k records, but want to delete only old records, I want to maintain the latest 100k records.
Below is a query i have tried, please anyone help me, how to prepare the query.
DELETE FROM audit_logs where
id not in (SELECT id from audit_logs order by ID DESC LIMIT 100000);
You could wrap into another select the subquery;
DELETE FROM audit_logs
WHERE id not in (SELECT t1.id
FROM ( SELECT id
FROM audit_logs
ORDER BY ID DESC
LIMIT 100000
) as t1
);
Or use NOT EXISTS :
DELETE FROM audit_logs a1
WHERE NOT EXISTS ( SELECT *
FROM ( SELECT id
FROM audit_logs a2
ORDER BY ID DESC
LIMIT 100000
) as t1
);
Read more on : https://dev.mysql.com/doc/refman/8.0/en/update.html
I have a big table of messages with date and room columns. and 2 billion rows.
now i want keep only last 50 messages for every room and delete previous messages.
can i do it with a fast query ?
this question is unique , i didn't found any other question for delete rows over a grouped and ordered selection
You cannot do it in a fast query. You have a lot of data.
I would suggest creating a new table. You can then replace the data in your first table, if necessary.
Possibly the most efficient method to get the 50 rows -- assuming that date is unique for each room:
select t.*
from t
where t.date >= coalesce((select t2.date
from t t2
where t2.room = t.room
order by t2.date desc
limit 1
), t.date
);
For this to have any hope of performance you want an index on (room, date).
You can also try row_number() in MySQL 8+:
select . . . -- list the columns
from (select t.*, row_number() over (partition by room order by date desc) as seqnum
from t
) t
where seqnum <= 50;
Then you can replace the data by doing:
create table temp_t as
select . . . -- one of the select queries here;
truncate table t; -- this gets rid of all the data, so be careful
insert into t
select *
from temp_t;
Massive inserts are much more efficient than massive updates, because the old data does not need to be logged (nor the pages locked and other things).
You can use Rank() function to get top 50 results for each group ordered by date desc, so the last entries will be in top.
http://www.mysqltutorial.org/mysql-window-functions/mysql-rank-function/
Then you left join that subquery on your table on id ( or room and date, if those are unique and you don’t have id in your table)
The last step would be to filter all such result that have null in subquery and delete those.
The full code will look something like this:
DELETE T FROM YOURTABLE T
LEFT JOIN (
SELECT *,
RANK() OVER (PARTITION BY
ROOM
ORDER BY
[DATE] DESC
) DATE_RANK
) AS T2
ON T.[DATE] = T2.[DATE]
AND T.ROOM = T2.ROOM
AND T2.DATE_RANK<=50
WHERE T2.DATE IS NULL
The problem
I'm using buddypress for Wordpress it has a table for private messages in side which are thread ids for message threads. Currently there's no limit on how many messages can be in a thread.
I want to create a command that deletes all but the most recent 10 messages in a thread. Below is the logic, but I'm not sure the correct syntax to do it?
Any of you mysql geniuses know the answer?
DELETE FROM TABLEA WHERE id = X delete everything with thread ID x
EXCEPT
(SELECT * FROM TABLEA WHERE id = X ORDER BY date_sent DESC LIMIT 10)
Selects most recent 10 I do not wish deleted.
This should working:
DELETE FROM TABLEA WHERE id = X AND id NOT IN (
SELECT TOP 10 id FROM TABLEA ORDER BY date_sent DESC
)
The sub-select of this query get the last 10 sent items. The main query have to delete the item with id X except the item is on the result of the sub-select.
I'm not sure how the table in buddypress works but I guess TABLEA should have its on primary key id. If TABLEA does have its own primary key id, here's my solution.
DELETE FROM TABLEA WHERE id = x AND TABLEA_id NOT IN
(SELECT TABLEA_id FROM TABLEA WHERE id = x ORDER BY date_sent DESC LIMIT 10)
I have a table with: id, pointId, pointValue with about 10.000.000 rows.
I have to to reduce it by deleting 90% rows, so I need to leave every tenth record, and delete any other.
Using id from table isn't good idea because this is not sequence of consecutive numbers.
How can I do it by query?
I am not sure why you really need to delete so many millions of records.
But, following approach may help you.
You can generate dynamic 'row_number' based on which you can filter every 10th row and delete rest of the records.
Example:
Assuming that the table name is 'points_table'.
delete from points_table
where id NOT IN (
select id from (
select #rn:=#rn+1 as row_num, p.id
from points_table p, (select #rn:=0) rn
) list_of_ids_to_be_deleted
where row_num % 10 = 0
)
You can try it:-
DELETE FROM TABLE_NAME
WHERE ID NOT IN
(SELECT ID FROM (SELECT #RN:=#RN+1, ID, POINTID, POINTVAL
FROM TABLE_NAME, (SELECT #RN:=0) T) T1
WHERE MOD(#RN,10) = 0)
This might help you.
A simple solution that should delete 90% of your rows assuming you've got 10 million rows.
DELETE FROM MyTable WHERE Id IN (SELECT Id FROM MyTable LIMIT 9000000);
http://sqlfiddle.com/#!2/d21f3/1
I have a table with some entries here, I want to keep only 50 messages in this table sorted by message_id, and DELETE the rest of entries.
Please help me with the query.
Thanks in advance.
E.g..
DELETE a
FROM chat_history a
LEFT
JOIN
( SELECT x.message_id
FROM chat_history x
JOIN chat_history y
ON y.message_id >= x.message_id
GROUP
BY x.message_id
HAVING COUNT(*) <= 50
) b
ON b.message_id = a.message_id
WHERE b.message_id IS NULL;
http://sqlfiddle.com/#!2/361b4/1
Try this one i have used ORDER BY message_id DESC change it as you want it will delete all except the seleted 50 entries, i have aliased the query because you cannot use same table to select with delete operation
DELETE FROM `chat_history` WHERE id NOT IN ( SELECT t.id FROM
(SELECT id FROM chat_history ORDER BY message_id DESC LIMIT 50 ) t)