2013-02-28 7 views
5

私はこれをどのようにフレーズするのかよく分かりませんが、本質的に互換性のある表を実装する良い方法はありますか?交換可能な列を表現する方法

例:ユーザーモデルがあり、2人のユーザーを「友人」にしたいとします。わかりやすい方法は、2つの列( 'friend1'と 'friend2')を含むテーブルを作成し、それぞれにユーザーのキーを格納することです。これは、 "(friend1 = user1 AND friend2 = user2)OR(friend1 = user2 AND friend2 = user1)"をチェックする必要があるため、 "user1 and user2 friends"のようなものを言うのは面倒です。それはうまくいくでしょうが、あなたがテーブルから何かを取得したいときはいつでも、両方の列を見ているということは、私には厄介なようです。よりエレガントな方法がありますか?

+0

は申し訳ありませんが、私は間違っているよう

class User < ActiveRecord::Base has_many :followings has_many :followers, :through => :followings, :class_name => "User" has_many :followees, :through => :followings, :class_name => "User" end class Following < ActiveRecord::Base # fields: follower_id followee_id (person being followed) belongs_to :follower, :class_name => "User" belongs_to :followee, :class_name => "User" end 

同じ例えば

- それがうまく動作しない(クエリは友情が間違っている見つけるために)。私は私の答えを削除します。 –

答えて

3

友情関係を作るときに重要な選択肢は、双方向性であるかどうかを判断することです。 Twitterは、一方向の友情とFacebookの友情の双方向性の一例です。あなたは双方向にコミットしているようにあなたが持っている2つのオプションがあるので、サウンド:

1)

select * 
from friendships 
where (friend1 = 123 and friend2 = 456) OR (friend2 = 123 and friend1 = 456) 

2両方向を確認してください)常ににfriend1と高いのuser_idに下のuser_idを置きますfriend2の場合、テストでは一方向のみをチェックする必要があります。これは維持するのが少し難しいので、私はそれをperfの理由から必要とします。

+1

双方向の友情は、私が行っていたことです、ありがとうございます。 friend2 = user1が) 組合 (友人 friend1からfriend2 を選択する場所であっても第二の選択肢で、まだいくつかの厄介なクエリ(例があるでしょうけれども。あなたは に持ってUser1の友人の一覧を表示するには '(友人 からfriend1 を選択= user1) ') – user1916823

1

これを実装する方法は少し不便かもしれません。アイデアは、friendshipIdとuserという2つの列を持つテーブルに "friendshipId"を持つことです。今やユーザーは交換可能です。

user1とuser2のが友達であるかどうかを調べるには:

select friendshipId 
from friends 
group by friendshipId 
having sum(case when name = user1 then 1 else 0 end) > 0 and 
     sum(case when name = user2 then 1 else 0 end) > 0 

トリガー、制約を適切に使用して、ストアドプロシージャは、友人関係は、誰かが友人に自分自身をすることはできませんし、そうすることを、2つだけのユーザーを持っていることを確認しますに。

+0

これはデータベースレベルで可能な最もリテラルな方法で関係の性質を表現する良い方法です。実際には、ドメインとユニークな制約とアプリケーション層での単純なヘルパー機能の組み合わせによって、これはぎこちないトリガーや厄介なsprocsなしで行うことができます。例えば、友人テーブルに 'Position'カラムを追加することができます(> 0、<= 2、' friendshipID'で一意)。起動するには、必要に応じて手動でデータを挿入するのは簡単です。私はたぶん 'having'節ではなく、self-joinでfriendテーブルを照会するでしょう。 – WCWedin

関連する問題