我使用的查询如下:
SELECT * FROM items ORDER BY RANDOM()
如果行数少,一切都好。然而,在我的测试中,我想有一些可复制的东西来验证。这就是为什么我要给随机数生成器植入种子:
SELECT setseed(0.123);
SELECT * FROM items ORDER BY RANDOM();
很好,工作很好。看起来每次执行的顺序都是一样的。只是它不是完全可复制的。在某些情况下,测试成功,我得到了预期的顺序和结果。在执行相同的测试时,我不知道。为什么?
我使用的查询如下:
SELECT * FROM items ORDER BY RANDOM()
如果行数少,一切都好。然而,在我的测试中,我想有一些可复制的东西来验证。这就是为什么我要给随机数生成器植入种子:
SELECT setseed(0.123);
SELECT * FROM items ORDER BY RANDOM();
很好,工作很好。看起来每次执行的顺序都是一样的。只是它不是完全可复制的。在某些情况下,测试成功,我得到了预期的顺序和结果。在执行相同的测试时,我不知道。为什么?
3条答案
按热度按时间nkoocmlb1#
这个问题与这样一个事实有关:行首先是按未指定的顺序(如果没有指定ORDERBY子句)获取的,然后才为每一行调用random()函数。这意味着在应用orderby random()之后,未指定的顺序将影响行顺序。
例如,在两种情况下使用相同的种子:
案例1
案例2
然后,解决方法是在按random()对行进行排序之前对行进行排序。最终结果是100%确定的。
ni65a41a2#
使用子查询可能会更好:
原因是
RANDOM()
在排序过程中多次调用。一些排序算法是不确定的——这会影响下游行。这不是100%保证,因为子查询仍然不能按顺序处理(尽管它应该在单处理器系统上)。但是您可以通过使用散列而不是随机值来进一步纠正这个问题。所以:
这个
item_id
假定每行上的值不同。这个'0.123'
是添加的,以便您可以轻松地更改顺序。2admgd593#
你似乎想要一个可重复的随机排序。
setseed()
是正确的方法,但是您需要在查询中设置它,因此它适用于random()
.下面是一个使用
union all
:这演示了如何处理只有一列的表。您可以通过添加更多的列来扩展它
null
列到第一个子查询(并相应地列出另一个子查询中的相应列)union all
外部查询中的成员和)。