2012-02-10 8 views
1

私は、単一のレコードが複数のレコードを別のテーブル(idとhas_manyステートメントによってリンクされている)になければならない検索を作成しようとしています。その結果として含まれています。Ruby on Rails:複数の行が別のテーブルに存在する必要があるテーブルを検索します

テーブルがあります。usersskill_listsskill_mapsです。

ユーザーは、skill_mapsテーブルの1つのエントリを通じて個々のスキルにマップされます。多くのユーザーは1つのスキルを共有でき、1人のユーザーはskill_mapsテーブルの複数のエントリを通じて多くのスキルを持つことができます。

User_id | Skill_list_id 
2  | 9 
2  | 15 
3  | 9 

ユーザー2は9と15
ユーザ3が、私はスキルのセットを持っているすべてのユーザーのハッシュを返す検索を作成しようとしているだけのスキル9

を持っているスキルを持っています。必要なセットskill_idsは、パラメータとして配列として表示されます。

skill_selection_user_ids = SkillMap.find_all_by_skill_list_id(params[:skill_ids]).map(&:user_id) 

@results = User.find(:all, :conditions => {:id => skill_selection_user_ids}) 

問題は、これがないそれらのすべてを持っているユーザーをこれらのスキルのいずれかを持っているすべてのユーザーを返すことです。

はここで私が使用しているコードです。

また、私のユーザーテーブルはskill_listsテーブル:through => :skill_mapsにリンクされており、その逆だから、私は、これは本当の初心者の質問であると確信している私はに全く新たなんだ...

@user.skill_listなどを呼び出すことができることレール(とプログラミング)。私は検索して解決策を探しましたが、何も見つかりませんでした。私は本当に単一の検索語で問題を説明する方法を知らない。

答えて

1

私は、ActiveRecordのクエリインターフェイスを使用してこれを行う方法を個人的にはわかりません。一番簡単な方法は、個々のスキルを持っているユーザーのリストを取得し、その後、おそらく設定使用して、これらのリストの交差点を取るために、次のようになります(おそらく)は、より高いパフォーマンスを得るために

require 'set' 

skills = [5, 10, 19] # for example 
user_ids = skills.map { |s| Set.new(SkillMap.find_all_by_skill_list_id(s).map(&:user_id)) }.reduce(:&) 
users = User.where(:id => user_ids.to_a) 

を、あなたは「ROLLことができ、あなたの独自の "SQLを実行し、DBエンジンに作業をさせます。ここで高性能が必要な場合は、私はあなたのためにいくつかのSQLを思いつくことができるかもしれません。

ちなみに、skill_mapsテーブルが非常に大きくなっても、良いパフォーマンスを確保するために、インデックスをskill_maps.skill_list_idに置くべきでしょう。 ActiveMigrationのドキュメントを参照してください。http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

+0

どうもありがとうございます! この新しいリストでユーザーテーブルを検索する前に.to_aを追加する必要がありました。最終的なコードは次のとおりです。 'skill_selection_user_ids = params [:teach_skill_ids] .map {| s | @results = User.find(:all、:conditions => {:id => skill_selection_user_ids.to_a})を使用すると、 ) ' もう一度ありがとう! – joshblour

+0

できました: '@results = User.find skill_selection_user_ids.entries'。 'entries'は、あなたが単に 'find'にフィードする配列にセットを変換します。 – dynex

+0

あまりにも働いた、ありがとう@dynex! – joshblour

1

おそらく、ユーザーIDを取得するためにカスタムSQLを使用する必要があります。私は同様のHABTM関係でこのクエリをテストしましたが、うまくいくようです:

SELECT DISTINCT(user_id) FROM skill_maps AS t1 WHERE (SELECT COUNT(skill_list_id) FROM skill_maps AS t2 WHERE t2.user_id = t1.user_id AND t2.skill_list_id IN (1,2,3)) = 3 

トリックはサブクエリにあります。外側のクエリの各行について、それはあなたが興味を持っているスキルの任意のと一致し、その行のレコードの数を検索します。そして、それはを数えるは、スキルの総数と一致するかどうかをチェックしますあなたは興味があります。一致するものがあれば、ユーザーはあなたが検索したすべてのスキルを持っていなければなりません。

あなたはfind_by_sqlを使用して、レールでこれを実行することができます:

sql = 'SELECT DISTINCT(user_id) FROM skill_maps AS t1 WHERE (SELECT COUNT(skill_list_id) FROM skill_maps AS t2 WHERE t2.user_id = t1.user_id AND t2.skill_list_id IN (?)) = ?' 
skill_ids = params[:skill_ids] 
user_ids = SkillMap.find_by_sql([sql, skill_ids, skill_ids.size]) 

申し訳ありませんが、テーブル名や列名が正確に右ではないですが、うまくいけば、これは球場内にある場合。

関連する問題