【问题标题】:How to randomly delete 20% of the rows in a SQLite table如何随机删除 SQLite 表中 20% 的行
【发布时间】:2011-05-17 22:00:34
【问题描述】:

下午好,我们想知道如何在一个有 15000 行的 sqlite 表中随机删除 20% 的行。我们注意到在 Stack Overflow 中使用 SQL Server Select n random rows from SQL Server table 解决了这个问题。 但是 SQL Server 脚本在 sqlite 中似乎无法正常运行。我们如何将 SQL Server 脚本转换为 sqlite 等效脚本?谢谢。

【问题讨论】:

标签: sqlite


【解决方案1】:

另外,由于 sqlite 中的 random() 函数返回一个有符号的 64 位整数,我们可以将这个空间内的一个点计算为 (2^63) * 0.6 。大于此的有符号整数将占正符号 64 位整数集的 40%,因此占整个集的 20%。

截断为下面的整数,这是 5534023222112865484 。

因此,您应该能够通过简单的方式获得 20% 的行:

   SELECT * FROM table WHERE random() > 5534023222112865485

或者在你的情况下,因为你想删除那么多:

   DELETE FROM table WHERE random() > 5534023222112865485

希望您喜欢这种方法。如果您希望从此类操作中获得高性能,它实际上可能是合适的,但它可能取决于硬件/版本,因此可能不值得冒险。

【讨论】:

  • 感谢您的回复。我只是试图接受你的回答。一旦我们运行 DELETE FROM table WHERE random() > 5534023222112865485 ,表中的 rowids 就会有间隙。你知道要运行哪些 sqlite 语句来缩小 rowid 差距吗?谢谢。
  • 作为一般的好习惯,您不应该关心 ROWID 的实际值,以及序列中是否可能存在间隙。由于各种原因,数据库在任何情况下都可能在正常使用过程中出现序列间隙。例如,当您开始时;插入;插入;犯罪;在您开始时在一个线程中;插入;回滚;在另一个线程中,您最终可能会在 ROWID 中出现空白。
  • 另外,正如有人在下面的评论中指出的那样,使用 WHERE (random() % 5) = 0 确实是一个更好的解决方案,因为它不需要花哨的大小计算64 位有符号整数,它没有可能依赖于硬件/版本。
  • 感谢您的回复。您对 rowid 中的空白的评论非常有帮助。您关于 where (random() % 5) 的第二条评论对我们也很有帮助,特别是因为我们希望我们的解决方案独立于硬件,谢谢。
【解决方案2】:

不是很“随机” - 但如果你在表上有一个标识列,你可以DELETE FROM mytable WHERE ID % 5 = 0 这应该从统计上删除非常接近五分之一的行。

【讨论】:

  • @Will A,谢谢您的回答。我刚刚接受了你的回答。我们表中唯一的标识列是隐式 ROWID 列。我们可以在您的答案中用 ROWID FOR ID 代替吗?谢谢你的建议。
  • @Frank - 很高兴,先生。是的,ROWID 没问题。
  • @Frank:你可以使用rowid。你也可以使用WHERE random() % 5 = 0
  • @WillA,谢谢你的回答。我会尽快尝试并告诉您我们的结果。
  • @Nick Dandoulakis,谢谢您的回答。我将在复制我的 sqlite 数据库后立即尝试。感谢您的帮助。
【解决方案3】:

试试:

DELETE FROM TABLE 
WHERE ROWID IN (SELECT ROWID FROM TABLE ORDER BY RANDOM() LIMIT 3000) 

如果要在子查询中计算 20%:LIMIT (SELECT CAST( ( COUNT(id) * 0.2 ) AS INT )

【讨论】:

  • @user589993,谢谢您的回答。我刚刚接受了你的回答。我们的 sqlite 表中没有 ID 列。我们可以使用 ROWID 代替 ID 吗?感谢您的帮助。
  • 是的,ROWID 也可以正常工作,而且您似乎接受了其他解决方案之一。
  • @user589993,谢谢您的回答。我会马上试一试,然后告诉你我们的结果。
  • @user589993,我试过你的答案。它运行得很快。我只是好奇我们是否可以在随机删除后使修改表中的 rowid 连续。感谢您的帮助。
【解决方案4】:

SQLite - ORDER BY RAND() 提供提示。因此这可能有效?

DELETE FROM table WHERE id IN(
    SELECT id FROM table ORDER BY RANDOM() LIMIT (
        SELECT CAST( ( COUNT(id) * 0.2 ) AS INT ) FROM table
    )
);

【讨论】:

  • 感谢您的回答。我刚刚接受了你的回答。我们可以在您的答案中用 ROWID 代替 ID。感谢您的帮助。
  • 我试过你的答案。它工作正常。我注意到现在 ROWID 中存在差距。是否可以使 ROWID 再次连续?感谢您的帮助。
  • @Frank,为了使ROWID 再次连续,您需要将数据复制到临时表,截断当前表,然后重新插入旧数据。但是,我同意其他关于无需担心的评论。
  • 对我来说,这看起来是唯一具有确切结果的答案,还是我忽略了某些东西?顺便说一句:CAST 不是必需的(至少对于版本 3.21.0)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 2022-01-13
相关资源
最近更新 更多