2012-12-20 49 views
4

我需要從db中選擇隨機記錄。在我用於開發的Sqlite3中,有一個名爲Random()的函數。但是,在Postgresql中,它被稱爲Rand()。我不記得MySql,但可能在那裏調用它。隨機選擇RoR中的不同數據庫

所以,如果我有一個代碼(SQLITE3)

data = Items.where(pubshied: is_pubshied).order("RANDOM()").limit(count) 

我如何確保它會與不同的數據庫?

+0

可能與http://stackoverflow.com/問題/ 5342270/rails-3-get-random-record –

+0

我已經在下面添加了我的答案,但應該說你的問題是錯誤的,在sqlite3和postgresql都使用'random()'只有mysql使用'rand()' –

+1

我對於你的問題Railsy解決方案的思考更多,但請注意,你剛剛遇到了你應該使用相同的數據庫系統進行開發和生產的原因。在本地安裝Postgres進行開發;這很值得。 –

回答

4

Rails不支持開箱即用。我相信我有一個模型擴展(我不使用它了,因爲我強制使用PostgreSQL的),但這樣的事情可以工作,取得了這一點:

module Randomize 
    extend ActiveSupport::Concern 

    included do 
    scope :random, -> { order(rand_cmd) } 
    end 

    module ClassMethods 
    def rand_cmd 
     if connection.adapter_name =~ /mysql/i 
     'rand()' 
     else 
     'random()' 
     end 
    end 
    end 
end 

然後,您可以做

class Item 
    include Randomize 
end 

Item.where(...).random.limit(...) 
+0

性能影響是一件大事。我無法想象有人在生產中選擇這樣做。 – pguardiario

+0

@pguardiario我不明白爲什麼有人會需要在生產中使用這個,說什麼性能影響什麼?一個方法調用? –

+0

我的意思是像'order by rand()'那樣的性能影響,除非我弄錯了,否則每次都需要讀取完整的磁盤。 – pguardiario

-1

從waldyr.ar在他的評論中提到的帖子的評論:https://stackoverflow.com/a/12038506/16784

Tl; dr:您可以使用Items.all.sample(count)。當然,這將檢索整個表格,並且可能對大型表格沒有用處。

+1

獲取所有項目是一個糟糕的主意。 –

+0

通過'RAND()'進行排序一般也很糟糕。這是否有用取決於預期的用途:對於小型表格,或者更可能的是,從表格中選擇較小的一種,「樣本」方法非常有用。如果表現是至關重要的,那麼就需要更精細的策略。這是一個務實的解決方案;如果有的話,我會很樂意回答如何提高績效的問題。 – Confusion

0

對於高性能,無適配器特定的方式隨機排序,填充隨機列,穿上它的索引並調用它是這樣的:

Foo.order("random_column > #{rand}").limit(1) 
+0

Downvoting,因爲這會給你每次相同的順序。此外,我*認爲*一旦你做減法,索引將不會被使用,所以這不利於性能。 –

+0

是的,它應該是一個>我認爲,無論如何你明白了。 – pguardiario

+0

有趣的,但我仍然不認爲這是一個很好的解決方案:你的'ORDER BY'子句將對某些記錄評估爲「TRUE」,對其他評估則爲'FALSE'。你總是會有越低的'random_column'值越接近開始比越高;只有這些部門之間的臨界點是隨機的。在每個分區內,排序都是不可預測的。這根本不比'ORDER BY'更好,甚至可能更糟糕,因爲它會迫使'random_column'的值更接近前端,所以隨機性會有很大偏差。 –