我有一個查詢需要從滿足兩列需求的表中獲取。所以如果我有users
列的表,age
和score
。活動記錄 - 其中IN有多個列
SELECT * FROM users where (age, score) IN ((5,6), (9,12), (22,44)..)
在我的web應用程序中,我從ajax請求中獲得這對,並且數目可能相當大。我如何爲此構造一個Active Record查詢?
我工作的Postgres數據庫
我有一個查詢需要從滿足兩列需求的表中獲取。所以如果我有users
列的表,age
和score
。活動記錄 - 其中IN有多個列
SELECT * FROM users where (age, score) IN ((5,6), (9,12), (22,44)..)
在我的web應用程序中,我從ajax請求中獲得這對,並且數目可能相當大。我如何爲此構造一個Active Record查詢?
我工作的Postgres數據庫
理想的情況下,我們將構建基於輸入查詢字符串。例如
ages_and_scores = [ [5, 6], [9, 12], [22, 44] ]
query_string = ages_and_scores.map do |pair|
"(age = #{pair[0]} AND score = #{pair[1]})"
end.join(" OR ")
# => (age = 5 AND score = 6) OR (age = 9 AND score = 12) OR (age = 22 AND score = 44)
最後,您的查詢就會
User.where(query_string)
您可以糾正如何構建查詢字符串,因爲ages_and_scores
是不同的格式,以我的例子的邏輯。
改進
ages_and_scores = [ [5, 6], [9, 12], [22, 44] ]
query_params = []
query_template = ages_and_scores.map{ |_| "(age = ? AND score = ?)" }.join(" OR ")
# => (age = ? AND score = ?) OR (age = ? AND score = ?) OR (age = ? AND score = ?)
User.where(query_template, *ages_and_scores.flatten)
嘿,你可以試試這個辦法在MySQL:
ages_and_scores = [ [5, 6], [9, 12], [22, 44] ]
User.where("CONCAT(age,',', score) in (?)",ages_and_scores.map{|b| "#{b[0]},#{b[1]}"})
在PG數據庫,你可以直接的毗連使用:
(age || ' ,' || score)
另一個解決方案是使用Arel,這將有助於保持東西D. B不可知論者。
ages_and_scores = [ [5, 6], [9, 12], [22, 44] ]
first_age, first_score = ages_and_scores.shift
t = User.arel_table
users = ages_and_scores.inject(User.where(t[:age].eq(first_age)).where(t[:score].eq(first_score))) { |query, age_score| query.or(User.where(t[:age].eq(age_score[0])).where(t[:score].eq(age_score[1]))) }
本質上是如何工作的:
Enumerable
的inject
方法模塊遍歷整個數組的其餘部分,並添加所有or
條件......但是從第一個where
查詢中的前兩個值開始。最後,您將有一個Arel
查詢,它將返回符合條件的所有用戶......並且它應該可以在Rails(Arel)支持的任何數據庫中工作。
這樣我會容易受到SQL注入嗎? – coderVishal
@coderVishal檢查我的改進 –
@coderVishal這有幫助嗎? –