【问题标题】:Loop through each ID with more than 3 records in the same table遍历同一张表中超过3条记录的每个ID
【发布时间】:2015-09-12 10:15:02
【问题描述】:

这是我的桌子:

placeID | name | time

如果 placeID 在表中的记录超过 3 条,我的目标是删除最旧的记录。

很难理解,举个例子就明白了:

1 | "Some Name" | *fresher timestamp*
1 | "Some Name" | *fresher timestamp*
1 | "Some Name" | *older timestamp* -- > Delete this result since there are more than 3 records, and this is the older than the rest
1 | "Some Name" | *older timestamp* -- > Delete this result since there are more than 3 records, and this is older than the rest
1 | "Some Name" | *fresher timestamp*
2 | "Some Name" | *fresher timestamp*
2 | "Some Name" | *fresher timestamp*

我的麻烦:我如何为每个在我的表中有超过 3 条记录的 placeID 循环?

删除最旧的结果不会有问题。

我尝试了什么:

SELECT placeID,COUNT(placeID) FROM place_fbStatus WHERE count(placeID) > 3

错误:#1111 - 组函数的使用无效

再试一次:

SELECT id, placeID
FROM place_fbStatus
HAVING COUNT( placeID ) >4
LIMIT 0 , 30

问题:只显示一个placeID

【问题讨论】:

    标签: mysql


    【解决方案1】:

    这是我的答案:

    首先是在您的表上创建一个主键。所以用这个很容易删除一行。

    创建表格:

    CREATE TABLE `mytable` (
      `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
      `placeID` INT(11) DEFAULT NULL,
      `name` VARCHAR(32) DEFAULT NULL,
      `time` TIMESTAMP NULL DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `placeID` (`placeID`,`time`)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    

    插入一些东西:

    INSERT INTO `mytable` (`id`, `placeID`, `name`, `time`)
    VALUES
        (1, 1, 'Some Name', '2015-01-01 00:00:00'),
        (2, 1, 'Some Name', '2015-01-02 00:00:00'),
        (3, 1, 'Some Name', '2015-01-10 00:00:00'),
        (4, 1, 'Some Name', '2015-01-09 00:00:00'),
        (5, 2, 'Some Name', '2015-02-01 00:00:00'),
        (6, 2, 'Some Name', '2015-01-30 00:00:00'),
        (7, 1, 'Some Name', '2015-01-08 00:00:00');
    

    我添加了删除(每个地方的 ROW ID)并且行的顺序正确

    SELECT @rid:=IF( @pid = m.placeID, @rid+1 , 1) rid, m.*, @pid:=m.placeID AS pid
          FROM mytable m, (SELECT @rid:=0, @pid:=-1) AS tmp 
          ORDER BY placeID,TIME ASC
    

    最后是删除行的查询:

    DELETE mt FROM mytable mt
    INNER JOIN (
      SELECT * FROM (
        SELECT @rid:=IF( @pid = m.placeID, @rid+1 , 1) rid, m.*, @pid:=m.placeID AS pid
          FROM mytable m, (SELECT @rid:=0, @pid:=-1) AS tmp 
          ORDER BY placeID,TIME ASC
      ) AS x
      WHERE x.rid >3
    ) AS dt ON mt.id = dt.id ;
    

    【讨论】:

    • 我不熟悉rid,但我试过了——它并没有删除任何记录。 x.rid 不应该是 x.pid?
    • 你能在这里发布一些数据吗,或者最好在sqlfiddle.com 上发布。请发布 CREATE 表
    • 您说您有一个 TIMESTAMP 但有一个 VARCHAR 字段。请显示其中的值并尝试我的孔示例(创建、插入和删除语句)
    • 对不起。它是 UNIX 时间戳。 (例如:1442082119)。我不认为这有什么关系。我将它存储为varchar。我认为您的查询应该在这两种情况下都有效,但它不是
    • 是的,没问题,但是找不到任何错误。我再次测试了它。您能否也发布您修改后的删除查询
    【解决方案2】:

    你几乎成功了。您需要的是结合 GROUP BY 和 HAVING

    SELECT placeID, count(placeID) AS cnt
      FROM place_fbStatus 
      GROUP BY placeID HAVING cnt>3
    

    【讨论】:

    • 当我在这两种情况下添加ORDER BY theTime ASCORDER BY theTime DESC 时,它会显示最旧的记录而不是最旧的记录..
    • 您的问题是:“我如何为每个在我的表中有超过 3 条记录的 placeID 循环?”如果您还需要删除较旧的记录,您可以使用@berndbuffen 的解决方案,它过于复杂,但它会起作用。
    【解决方案3】:
    DELETE FROM Table WHERE ID NOT IN (SELECT TOP 3 ID FROM Table)
    

    参考this thread

    虽然,在我自己尝试之后,似乎某些版本的 mysql 尚不支持子查询中的限制子句(此版本的 MySQL 尚不支持 'LIMIT & IN/ALL/ANY/SOME 子查询')。要解决此问题,请尝试使用不涉及限制的备用子查询。

    【讨论】:

      猜你喜欢
      • 2020-01-13
      • 1970-01-01
      • 2014-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-21
      • 1970-01-01
      • 2017-05-21
      相关资源
      最近更新 更多