views:

591

answers:

1

I've got a table containing many rows. The rows are guaranteed to have been inserted in order of a column called created_on, which is a datetime column. If a given row has a created_on time within 5 seconds of an existing row, I'd like to delete the given row.

How would I write a query to delete those rows?

+1  A: 
SELECT *
FROM TABLE AS A
WHERE EXISTS (
    SELECT *
    FROM TABLE AS B
    WHERE DATE_SUB(A.created_on, INTERVAL 5 SECOND) <= B.created_on
        AND B.created_on < A.created_on
)

You understand that this will basically delete all chains of events within 5 seconds of each other, except for the first event in the chain.

Because you cannot alias a table in a DELETE, you'll have to do something like this:

DELETE
FROM   so902859
WHERE   created_on IN (
        SELECT  created_on
        FROM   so902859 AS A
        WHERE   EXISTS ( SELECT *
                         FROM  so902859 AS B
                         WHERE  DATE_SUB(A.created_on, INTERVAL 5 SECOND) <= B.created_on
                                AND B.created_on < A.created_on ) )

There are a million ways to skins this cat using JOINs or whatever. I think this one is the most clearly understandable, if a bit lengthy.

Cade Roux
Yep, that's what I'm aiming for. Thanks, I'll give this a shot.
Kyle Kaitan
Hm, I get a syntax error when I use this. Here's the query, in brackets: [[ delete from sessions as lhs where exists ( select * from sessions as rhs where date_sub(lhs.created_at, interval 5 second) <= rhs.created_at and rhs.created_at < lhs.created_at ); ]]And here's the error message: ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where exists ( select * from sessions as rhs where date_sub(lhs.created_at, inte' at line 1
Kyle Kaitan
AFAIK `where exists` doesn't work with `delete`, just `select`. I'm not sure how to formulate it to work in one query.
Schwern
It's not a problem with EXISTS, it's a problem with aliasing. See my updated answer.
Cade Roux
And this goes to show just how unearthly unhelpful the error messages mysql produces are.
shylent
Cade: Thanks for your update. Is "so902859" intended to be replaced with my table name? (In this case it's 'sessions').
Kyle Kaitan
Yes, sorry, when I am duplicating the problems in my installation, I name the test table so# where # is the ID of the question ("so" stands for StackOverflow, of course).
Cade Roux