Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL Specialists: Delete all rows older than x days but not the latest one

Tags:

mysql

first of all, this is the query which creates the "player history" it can be executed as often as you want and it will only create new history rows for the players if there is no history row for yesterday or if the values changed since the latest history entry in the past.

INSERT INTO `player_history` (`player_id`, `date`, `races`, `maps`, `playtime`, `points`)
SELECT `p`.`id`, DATE_SUB(NOW(), INTERVAL 1 DAY), `p`.`races`, `p`.`maps`, `p`.`playtime`, `p`.`points`
FROM `player` `p`
WHERE `p`.`playtime` IS NOT NULL
AND `p`.`playtime` > 0
AND (
    SELECT `player_id`
    FROM `player_history`^
    WHERE `player_id` = `p`.`id`
    AND (
        `date` = DATE_SUB(NOW(), INTERVAL 1 DAY)
        OR (
            `date` < DATE_SUB(NOW(), INTERVAL 1 DAY)
            AND `races` = `p`.`races`
            AND `points` = `p`.`points`
            AND `maps` = `p`.`maps`
            AND `playtime` = `p`.`playtime`
        )
    )
    ORDER BY `date` DESC
    LIMIT 1
) IS NULL;

now the problem is i also want to cleanup the history table using a single query. this already selects all history entries older than 10 days but the latest. but i cant just like do DELETE instead of SELECT *.

SELECT *
FROM `player_history` `ph`
WHERE `date` < DATE_SUB(NOW(), INTERVAL 10 DAY)
AND `date` != (SELECT `date`
    FROM `player_history`
    WHERE `player_id` = `ph`.`player_id`
    ORDER BY `date` DESC
    LIMIT 1);

so is tehre a way to do what i want using a single delete query?

like image 927
Andreas Linden Avatar asked Oct 13 '10 21:10

Andreas Linden


People also ask

How do I purge old data in MySQL?

To delete all rows older than 30 days, you need to use the DELETE with INTERVAL. Use < now() i.e. less than operator to get all the records before the current date.

How do I DELETE last record and give the latest records in MySQL?

The syntax is as follows: DELETE FROM yourTableName WHERE yourColumnName1=yourValue ORDER BY yourColumnName2 DESC LIMIT 1; The above syntax will delete last record (on condition) from a table. It sorts the column in descending order and choose the first element to delete.

Is there a faster way to delete all table rows than to use a DELETE query?

TRUNCATE is faster than DELETE , as it doesn't scan every record before removing it. TRUNCATE TABLE locks the whole table to remove data from a table; thus, this command also uses less transaction space than DELETE . Unlike DELETE , TRUNCATE does not return the number of rows deleted from the table.

Can we use limit in DELETE query?

It is used in the DELETE LIMIT statement so that you can order the results and target those records that you wish to delete. It specifies a limited number of rows in the result set to delete based on row_count. For example, LIMIT 10 would delete the first 10 rows matching the delete criteria.


2 Answers

Your query looks right in my eyes but you don't have the interval in the subquery.

I would do this:

DELETE FROM player_history
WHERE date < DATE_SUB(NOW(), INTERVAL 10 DAY)
AND date != (
    SELECT MAX(date) FROM player_history
    WHERE date < DATE_SUB(NOW(), INTERVAL 10 DAY)
)

What's the error message from mysql?

like image 65
Jürgen Steinblock Avatar answered Oct 06 '22 05:10

Jürgen Steinblock


Probably you can't do this in a single query because the documentation states:

Currently, you cannot delete from a table and select from the same table in a subquery.

As a workaround you could select the ids of the rows that have to be deleted into a temporary table and then use a multi-table delete statement to delete the records from the original table.

like image 30
Mark Byers Avatar answered Oct 06 '22 05:10

Mark Byers