我试图填充列中的每一行,随机范围从0到行计数。 到目前为止我有这个
UPDATE table
SET column = ABS (RANDOM() % (SELECT COUNT(id) FROM table))
这可以完成工作,但会产生重复的值,结果证明是坏的。我添加了一个唯一约束,但这只会导致它崩溃。
有没有办法使用某个范围内的随机唯一值更新列?
谢谢!
答案 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语句时。但是使用数组驱动单例更新可能几乎一样简单。在此更新过程中,您可能不希望对随机数列有唯一约束。