2010-11-17 116 views
16

我正在使用「where」語法編寫Rails 3 ActiveRecord查詢,它使用SQL IN和SQL OR運算符,並且無法弄清楚如何一起使用它們。Rails 3使用SQL IN和SQL OR運算符的ActiveRecord查詢

此代碼(在我的用戶模型):

Question.where(:user_id => self.friends.ids) 
#note: self.friends.ids returns an array of integers 

但是這個代碼

Question.where(:user_id => self.friends.ids OR :target => self.friends.usernames) 

返回該錯誤

syntax error, unexpected tCONSTANT, expecting ')' 
...user_id => self.friends.ids OR :target => self.friends.usern... 

不知道如何在Rails中寫這篇文章,或者只是原始的SQL查詢應該是什麼?

回答

-7

原始SQL

SELECT * 
FROM table 
WHERE user_id in (LIST OF friend.ids) OR target in (LIST OF friends.usernames) 

每個列表逗號分隔。我不太瞭解Rails ActiveRecord的東西。對於和你只想把那兩個條件之間用逗號,但IDK的約OR

+0

謝謝!我使用的確切查詢是:Question.where('target IN(?)OR user_id IN(?)',self.friends.usernames,self.friends.ids) – kateray 2010-11-17 20:23:01

+0

好,我忘記了。我覺得他們應該是=>散列格式中的一種方式。你不應該需要一個字符串模式來在兩個有效的條件之間添加OR,但是誰在乎你。 – 2010-11-17 20:26:48

+13

主動記錄的想法是數據庫不可知的,所以在rails中使用原始sql不應該被認爲是最好的解決方案,除非性能降低,而在這個查詢中情況並非如此。 – nunopolonia 2011-08-08 14:13:40

45

你並不需要使用原始SQL,只需提供模式作爲一個字符串,並添加一個名爲參數:

Question.where('user_id in (:ids) or target in (:usernames)', 
       :ids => self.friends.ids, :usernames => self.friends.usernames) 

或位置參數:

Question.where('user_id in (?) or target in (?)', 
       self.friends.ids, self.friends.usernames) 

您也可以使用優秀Squeel寶石,如@erroric指出了他的答案(只需要my { }塊,如果你需要訪問self個或實例變量):

Question.where { user_id.in(my { self.friends.ids }) | 
       target.in(my { self.friends.usernames }) } 
+0

嘿人類需要幫助..如何編寫查詢,如果我需要選擇兩個用戶之間的所有消息(說id1&id2)和消息有sender_id和receiver_id。所以我需要選擇「((sender_id = id1和reciver_id = id2)或(sender_id = id2和reciver_id = id1))」的所有消息。我需要對它們進行排序和分頁,如果我做兩個單獨的查詢然後添加它們(我將得到期望的結果,但分頁變得困難),這是無法完成的。所以請幫我寫單行查詢。任何幫助將不勝感激。 – zeal 2014-08-06 20:23:17

+0

@zeal,請打開一個新問題,描述你已經嘗試了什麼以及我們如何提供幫助。社區很棒,但你必須學會​​如何使用它。 – 2014-08-07 03:09:14

9

雖然Rails 3的AR不給你或操作員仍然可以達到同樣的效果,而不去一路下跌到SQL和直接使用阿雷爾。我的意思是,你可以做這樣的:

t = Question.arel_table 
Question.where(t[:user_id].in(self.friends.ids).or(t[:username].in(self.friends.usernames))) 

也許有人會說這是不是很漂亮,有人可能會說這是很簡單,因爲它不包含SQL。無論如何它肯定會是漂亮,有一個爲它的寶石太:MetaWhere

欲瞭解更多信息請參閱本railscast:http://railscasts.com/episodes/215-advanced-queries-in-rails-3 和MetaWhere網站:http://metautonomo.us/projects/metawhere/

UPDATE:後來瑞安貝茨取得了約metawhere另一個railscast和元搜索:http://railscasts.com/episodes/251-metawhere-metasearch 雖然後來Metawhere(和搜索)已經成爲或多或少遺留寶石。即他們甚至不使用Rails 3.1。作者覺得他們(Metawhere和搜索)需要徹底改寫。這麼多,他實際上一起去尋找新的寶石。 Metawhere的繼任者是Squeel。瞭解更多關於作者聲明此: http://erniemiller.org/2011/08/31/rails-3-1-and-the-future-of-metawhere-and-metasearch/ ,並檢查了項目主頁: http://erniemiller.org/projects/squeel/ 「元搜索2.0」被稱爲洗劫,您可以從這裏讀到關於它: http://erniemiller.org/2011/04/01/ransack-the-library-formerly-known-as-metasearch-2-0/

6

或者,你可以使用Squeel。在我看來,這很簡單。你可以做到既IN(>>)和OR(|)操作使用的語法如下:

Question.where{(:user_id >> my{friends.id}) | (:target >> my{friends.usernames})} 

我一般纏上了我的條件(...),以確保適當的操作順序 - 兩個或之前諸IN發生。

my{...}塊執行在Squeel調用之前定義的self上下文中的方法 - 在此例中爲Question。在Squeel塊內部,self是指Squeel對象而不是Question對象(see the Squeel Readme for more)。您通過使用my{...}包裝來恢復原始上下文。

+1

看起來不錯,但他們[倒下活動記錄的'where()'](https://github.com/ernie/squeel#compatibility-with-active-record),這似乎是不幸的。 – crizCraig 2013-06-11 22:26:02