如何从MySQL表中选择数据并删除其他所有内容?

时间:2014-04-29 17:35:43

标签: mysql

我有一个像这样的简单MySQL表:

CREATE TABLE `logins` (
  `user` int(10) NOT NULL,
  `time` int(10) NOT NULL,
  `ip` varchar(20) NOT NULL,
  PRIMARY KEY (`user`,`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

对于CRON,每24小时,我正在对这个表进行清理,我只保留每个用户IP的唯一登录,即如果某个用户从IP X登录5次,我只保留< strong>最新他使用该IP登录并删除剩余的4个。

这是我的QUERY:

DELETE FROM `logins` WHERE (`user`, `time`) NOT IN(
   SELECT `user`, `maxtime`
   FROM(
      SELECT `user`, MAX(`time`) as `maxtime` FROM `logins` GROUP BY `user`, `ip`
   ) as `a`
)

这种查询 - 子查询方式有点慢。完成大约需要3秒钟。

然而,内部部分非常快。如果我只遗漏SELECT部分​​,就像这样:

SELECT `user`, MAX(`time`) as `maxtime` FROM `logins` GROUP BY `user`, `ip`

只需不到0.005秒。

所以我想知道:如果我做了相反的事情会怎样?不是'除了X之外全部删除',而是“选择X,全部删除,重新插入X”?

这可能吗?

这样的事情:

1) SELECT `user`, MAX(`time`) as `maxtime` FROM `logins` GROUP BY `user`, `ip`
/* store this somewhere temporarily */

2) TRUNCATE TABLE `logins`

3) reinsert data from step 1 to `logins`

2 个答案:

答案 0 :(得分:2)

使用另一个(临时或非临时)表来插入要保留的数据。截短。然后插回来......

INSERT INTO LoginsTemp 
SELECT * FROM Logins WHERE ...; 

TRUNCATE Logins; 

INSERT INTO Logins 
SELECT * FROM LoginsTemp; 

答案 1 :(得分:1)

我会用它来删除除用户和ip的每个组合的最新记录之外的所有记录:

DELETE l1.*
FROM
  logins l1 INNER JOIN logins l2
  ON l1.user=l2.user
     AND l1.ip=l2.ip
     AND l1.time<l2.time

请参阅小提琴here