SQLite - 使用随机唯一值进行更新

时间:2012-12-15 20:05:33

标签: sqlite random unique

我试图填充列中的每一行,随机范围从0到行计数。 到目前为止我有这个

UPDATE table
SET column = ABS (RANDOM() % (SELECT COUNT(id) FROM table))

这可以完成工作,但会产生重复的值,结果证明是坏的。我添加了一个唯一约束,但这只会导致它崩溃。

有没有办法使用某个范围内的随机唯一值更新列?

谢谢!

2 个答案:

答案 0 :(得分:2)

如果您想稍后以随机顺序阅读记录,那么您可以在那时进行排序:

SELECT * FROM MyTable ORDER BY random()

(如果您在多个查询中需要相同的订单,则无效。)


否则,您可以使用临时表来存储表的rowid和数字1..N之间的随机映射。 (这些数字由临时表的rowid自动生成。)

CREATE TEMP TABLE MyOrder AS
  SELECT rowid AS original_rowid
  FROM MyTable
  ORDER BY random();
UPDATE MyTable
  SET MyColumn = (SELECT rowid
                  FROM MyOrder
                  WHERE original_rowid = MyTable.rowid) - 1;
DROP TABLE MyOrder;

答案 1 :(得分:1)

你似乎寻求的不仅仅是一组随机数,而是数字1..N的随机排列。这很难做到。如果您查看Knuth(计算机编程的艺术)或Bentley(编程珍珠或更多编程珍珠),建议的方法是创建一个值为1..N的数组,然后为每个位置交换当前从数组中随机选择的其他值的值。 (我需要挖出书来检查它是否是数组中的任意位置,或者只是在数组中跟随它的值。)在您的上下文中,然后将此排列应用于表格中的行一些排序,因此排序下的第1行获取位置1的数组中的值(使用基于1的索引)等。

在珍珠编程第1版第11栏搜索中,宾利说:

  

第3.4.2节中的Knuth算法P改组了数组X [1..N]。

for I := 1 to N do
    Swap(X[I], X[RandInt(I,N)])

其中RandInt(n,m)函数返回[n..m](包括)范围内的随机整数。如果不简洁,那就没什么了。

另一种方法是在有一个值需要更新时让代码抖动,等待随机数生成器选择一个尚未使用的值。作为一个命中和未命中过程,这可能需要一段时间,特别是如果总行数很大。

实际上将其翻译成SQLite是一项单独的练习。你的桌子有多大?是否有一个方便的唯一键(除了你随机的那个)?


假设您有一个主键,您可以轻松生成一个结构数组,以便为​​每个主键分配一个1..N范围内的数字。然后使用算法P来置换数字。然后,您可以使用适当的随机数从主键更新表。您可以使用SQL中的第二个(临时)表来完成所有操作,尤其是当SQLite支持具有两个表之间的连接的UPDATE语句时。但是使用数组驱动单例更新可能几乎一样简单。在此更新过程中,您可能不希望对随机数列有唯一约束。