我正在尝试用从 0 到行数的随机值填充列中的每一行。到目前为止我有这个
UPDATE table
SET column = ABS (RANDOM() % (SELECT COUNT(id) FROM table))
这可以完成工作,但会产生重复的值,结果很糟糕。我添加了一个唯一约束,但这只会导致它崩溃。
有没有办法用特定范围内的随机唯一值更新列?
谢谢!
如果您想稍后以随机顺序读取记录,您可以在当时进行排序:
SELECT * FROM MyTable ORDER BY random()
(如果您在多个查询中需要相同的顺序,这将不起作用。)
否则,您可以使用临时表来存储表的rowid
s 和数字 1..N 之间的随机映射。(这些数字是由rowid
临时表的 s 自动生成的。)
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..N 的随机排列。这更难做到。如果您查看 Knuth(计算机编程艺术)或 Bentley(编程珍珠或更多编程珍珠),建议的一种方法是创建一个值为 1..N 的数组,然后为每个位置交换当前位置值与从数组中随机选择的其他值。(我需要挖掘书籍以检查它是否是数组中的任意位置,或者仅在数组中跟随它的值。)在您的上下文中,然后将此排列应用于下表中的行一些排序,因此排序下的第 1 行获取数组中位置 1 的值(使用基于 1 的索引)等。
在 Programming Pearls 的第 1 版第 11 列搜索中,Bentley 说:
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 语句。但是使用数组来驱动单例更新可能几乎一样简单。在此更新进行时,您可能不希望对随机数列有唯一约束。