输出“随机”记录

时间:2011-07-05 14:29:30

标签: sql ruby-on-rails

表格 - 联系人

Name     Channel
Teejay   Friends
John     Colleagues
Rick     Friends
Carl     Business
Vulcan   Business
Scott    Office
Alex     Friends

如何从这个表中“随机”输出记录。好吧,不完全是random。我应该能够输出其中没有相同Channel的记录彼此相邻的记录。

A record in the `Friends` Channel
A record in the `Colleagues` Channel
A record in the `Business` Channel
A record in the `Office` Channel
A record in the `Friends` Channel
A record in the `Business` Channel
A record in the `Friends` Channel

更多信息:

朋友模型,同事模型,商业模式,Office模型是联系人的子模型。

1 个答案:

答案 0 :(得分:1)

您如何看待这个?

[ Friend, Colleague, Business, Office ].each do |klass|
  klass.find(:first, :offset => (klass.count * rand).to_i, :limit => 1)
end

从每个子模型中获取一个条目。这不会那么快,但有效:)

如果需要两次迭代,可以将整个块包装成:

2.times do
end

但请注意,此处修复了模型的顺序。如果您也需要随机:

prev = nil
10.times do
  klass = [ Friend, Colleague, Business, Office ].reject { |k| k == prev }.shuffle.first
  p klass.find(:first, :offset => (klass.count * rand).to_i, :limit => 1)
  prev = klass
end

更新

为了好奇,我为此做了一个小方法。请注意,如果您使用的是SQLite,则需要将RAND()替换为RANDOM()。请检查this question

def get_random_items(classes, count)
  # collect at least count / 2 random items from each class
  items = Hash.new do |hash,klass|
    hash[klass] = klass.find(:all, :order => "RAND()", :limit => (count.to_f / 2).ceil)
  end

  results = []
  prev = nil

  while (classes.length > 0 && results.length < count) do
    klass = classes.shuffle!.pop

    item = items[klass].pop
    next unless item

    classes << prev if prev
    prev = (items[klass].length > 0) ? klass : nil
    results << item
  end

  results

end

用法:get_random_items([ Friend, Colleague, Business, Office ], 10)