Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何有效地(以独立于数据库的方式)从表中选择随机记录?_Sql_Ruby On Rails_Activerecord - Fatal编程技术网

Sql 如何有效地(以独立于数据库的方式)从表中选择随机记录?

Sql 如何有效地(以独立于数据库的方式)从表中选择随机记录?,sql,ruby-on-rails,activerecord,Sql,Ruby On Rails,Activerecord,这似乎是一个非常简单的问题,但它并没有像我预期的那么简单 我有一个俱乐部有俱乐部成员,我想从一个俱乐部中随机抽出两名成员 使用RANDOM() 一种方法是使用随机排序: club.members.find(:all, :order => 'RANDOM()').limit(2) 但是,对于SqLite(开发数据库)和Postgres(生产数据库),这是不同的,因为在MySql中,命令是RAND() 虽然我可以开始写一些关于这一点的包装,但我觉得事实上,它还没有完成,而且似乎不是Activ

这似乎是一个非常简单的问题,但它并没有像我预期的那么简单

我有一个俱乐部有俱乐部成员,我想从一个俱乐部中随机抽出两名成员

使用RANDOM()

一种方法是使用随机排序:

club.members.find(:all, :order => 'RANDOM()').limit(2)
但是,对于SqLite(开发数据库)和Postgres(生产数据库),这是不同的,因为在MySql中,命令是
RAND()

虽然我可以开始写一些关于这一点的包装,但我觉得事实上,它还没有完成,而且似乎不是ActiveRecord的一部分,这告诉我一些事情,随机可能不是正确的方式

直接使用项目的索引将项目取出

另一种方法是按顺序提取集合,然后从中选择随机记录:

首先,我们需要生成与成员对应的两个唯一索引序列:

all_indices = 1..club.members.count
two_rand_indices = all_indices.to_a.shuffle.slice(0,2)
这将生成一个具有两个保证唯一和随机的索引的数组。我们可以使用这些索引来提取我们的记录

@user1, @user2 = Club.members.values_at(*two_rand_indices)
最好的方法是什么?

虽然第二种方法看起来很不错,但我也觉得我可能遗漏了一些东西,可能把一个简单的问题复杂化了。很明显,我不是第一个解决这个问题的人,那么通过它的最佳、最高效的SQL方法是什么?

MySQL中的Order By RAND()函数:

ORDER BY RAND() LIMIT 4

当上面是查询中的最后一个子句时,这将随机选择4行。

尝试使用gem,它实现了您提到的第二种方法。

第一种方法的问题是,它通过不可索引的表达式对整个表进行排序,只取两行。这不能很好地扩展

第二种方法的问题类似,如果表中有109行,那么将从
到\u a
生成一个大数组。这将需要大量的内存和时间来洗牌它

另外,通过在处使用
values\u,您不认为从1到count的每个主键值都有一行,没有间隔吗?你不应该这样想

我的建议是:

  • 计算表中的行数

    c = Club.members.count
    
  • 在1和计数之间

    r_a = 2.times.map{ 1+Random.rand(c) }
    
  • 使用查询您的表。
    不要使用
    orderby
    ,只需依赖RDBMS的任意排序即可

    for r in r_a
        row = Club.members.limit(1).offset(r)
    end
    
  • 另见:


    没有真正有效的独立于数据库的方法。为什么您需要它独立于数据库?这实际上取决于数据库以及您希望结果的随机性。@mitchwheat我正在SqLite上开发并部署在PosGres上,因此需要它同时跨数据库和随机性。我还希望尽可能多地编写与DB无关的代码作为良好的实践。约翰-我只是在寻找合理的随机性,不一定是真正的随机性。Craig-tyIt会的,但要以全表扫描为代价。