如何表示可互换的列

时间:2013-02-28 19:09:23

标签: sql ruby-on-rails erd

我不太确定如何表达这一点,但有没有一种很好的方法来实现一个表格,其中列基本上是可以互换的?

示例:您有一个用户模型,并希望允许两个用户成为“朋友”。对我来说,显而易见的方法是拥有一个包含两列('friend1'和'friend2')的表,每个列包含一个User的键。因为你必须检查“(friend1 = user1 AND friend2 = user2)OR(friend1 = user2 AND friend2 = user1)”,这使得说“是user1和user2朋友”之类的东西很尴尬。它会起作用,但对我来说这似乎很尴尬,每当你想要从那张桌子上得到一些东西时,你就会看到两个列。这样做有更优雅的方式吗?

3 个答案:

答案 0 :(得分:3)

建立友谊关系时的关键选择是决定它是否是双向的。推特之后是一个定向友谊和Facebook友谊双向的例子。听起来你已经致力于双向,所以你有两个选择:

1)检查两个方向

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

2)始终将较低的user_id放入friend1,将较高的user_id放入friend2,然后您的测试只需检查一个方向。这有点难以维护,所以我只是因为性能原因而需要它。

答案 1 :(得分:1)

你可以实现这一点的方式看起来有点尴尬。我们的想法是在一个包含两列的表中有一个“friendshipId”:friendshipId和user。现在用户可以互换。

要了解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)

您可以执行has_many through或has_and_belongs_to_many http://guides.rubyonrails.org/association_basics.html

您想要一个链接您的用户模型的连接表的方式。

例如

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

user has many :users, or must I use another way for a friend based social network?

相同