删除序列中的重复记录

时间:2014-12-19 12:11:13

标签: mysql

我创建了一个"登录"用于存储用户登录详细信息的表,如下所示(带有示例数据)。

CREATE TABLE Login ( id int(11) NOT NULL AUTO_INCREMENT, userid int(11) DEFAULT NULL, logintime timestamp NULL DEFAULT CURRENT_TIMESTAMP, status tinyint(4) NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;

INSERT INTO Login (id, userid, logintime, status)
values (1,  1,  '2014-12-19 16:27:46',  -1),
       (2,  1,  '2014-12-19 16:31:18',  -1),
       (3,  1,  '2014-12-19 16:31:27',  -1),
       (4,  1,  '2014-12-19 16:31:29',  -1),
       (5,  1,  '2014-12-19 16:31:41',  1),
       (6,  2,  '2014-12-19 16:32:01',  -1),
       (7,  2,  '2014-12-19 16:32:03',  -1),
       (8,  1,  '2014-12-19 16:32:06',  -1),
       (9,  1,  '2014-12-19 16:32:37',  -1),
       (10, 2,  '2014-12-19 16:32:58',  1),
       (11, 3,  '2014-12-19 16:33:05',  1),
       (12, 4,  '2014-12-19 16:33:10',  -1),
       (13, 4,  '2014-12-19 16:33:11',  -1),
       (14, 4,  '2014-12-19 16:33:11',  -1),
       (15, 5,  '2014-12-19 16:33:16',  -1),
       (16, 3,  '2014-12-19 16:33:19',  1),
       (17, 3,  '2014-12-19 16:34:39',  1);

在此示例中,字段status = 1显示成功登录,而status = -1显示登录失败。

在这里,我想删除重复的失败登录(例如,状态= -1)记录,除了第一条记录中的记录。
在我的情况下,用户1使用loginid 2,3,4的方法应该被删除,因为它是在loginid 1之后的一个sequance中。 然后用户1登录成功登录5(状态= 1),所以应该保留, 在用户1的loginid 9之后,还应删除,因为它是重复记录。

我想为每个用户执行此操作,此表至少有1400万(非常巨大),我想用DELETE查询来做。他们的任何查询都是这样做的吗?

2 个答案:

答案 0 :(得分:1)

首先,我建议您不要将其视为delete。而是将所需数据复制到另一个表,截断表,然后重新插入。

我建议使用变量来获得你想要的东西。以下标识您想要的记录:

select l.*
from (select l.*,
             (@rn := if(@id = id and status = -1, @rn + 1,
                        if(@id := id, 1, 1)
                       )
             ) as rn
      from login l cross join
           (select @rn := 0, @id := 0) vars
      order by id
     ) l
where seqnum = 1 or status = 1;

注意:测试此查询以确保它确实可以执行您想要的操作。

要使用它:

create table tmp_login as
    select l.*
    from (select l.*,
                 (@rn := if(@id = id and status = -1, @rn + 1,
                            if(@id := id, 1, 1)
                           )
                 ) as rn
          from login l cross join
               (select @rn := 0, @id := 0) vars
          order by id
         ) l
    where seqnum = 1 or status = 1;

truncate table login;

insert into login(id, userid, logintime, status)
    select id, userid, logintime, status
    from tmp_login;

答案 1 :(得分:0)

我写了这个查询,请先试试(先备份,哈哈):

DELETE FROM Login
WHERE id NOT IN (
    SELECT id
    FROM (
        SELECT DISTINCT LoginDelete.id
        FROM Login LoginDelete
        LEFT JOIN Login LoginIgnore
          ON LoginIgnore.userid = LoginDelete.userid
            AND LoginIgnore.status = LoginDelete.status
            AND LoginIgnore.id < LoginDelete.id
        WHERE LoginDelete.status = -1
          AND LoginIgnore.id IS NULL
    ) as idList
)

此查询将执行的操作是删除每个用户的每个状态= -1,但第一次记录除外。我使用了id,因为它应该是唯一的,如果在同一时间失败两次,则可以重复登录时间。

问候。