根据社交网络设计,我需要存储某人是否有Liked
或Disliked
。他们还可以采取其他行动,例如Share
。
我需要做的是确保当一个人Like
某事时,其值存储为true
。但如果他们改变主意并Dislike
同样的事情,则Like
'd值设置为NULL
,Dislike
值设置为true
}。
最初的方法是这样的表格:
UserID (int) | ItemID (int) | Like (bit) | Dislike (bit) | Share (bit) | ...
1 1 1 NULL NULL
1 2 NULL 1 NULL
1 3 1 NULL 1
这里的问题是,如果可以对某个项目采取更多操作,例如'Favourited'然后我必须将这些列添加到表中。这打破了规范化规则,但它可以工作。重要的商业规则是,某人不能Like
和Dislike
同时Item
。它的一个或另一个。我想我必须在应用程序端而不是数据库结束时进行逻辑处理,但是如果有更好的方法请告诉我!
另一种方法可能是拥有一个存储用户操作的表,如下所示:
ActionID | ActionName
1 Like
2 Dislike
3 Share
然后有一个像这样的链接表:
UserID | ItemID | ActionID
1 1 1
1 1 2
1 1 3
第二种方法的问题在于我认为很难使行动相互排斥。用户已经获得了一个项目,然后不喜欢它,然后共享它。因此,在我的应用程序中,我必须确定哪个ActionID与Like或Dislike相关,然后根据选择哪个,删除另一个。所以在这里我必须删除ActionID值为'1'的行,因为它被值为'2'的Dislike操作覆盖
任何人都可以建议最好的方法是什么?它是导致我最烦的某些行为之间的相互排他性。
答案 0 :(得分:1)
或者,您可以将其重新实现为整数列,并允许(-1,0,1)表示(不喜欢,中立等),这反过来可以简化项目的受欢迎程度。例如,列出前10个最喜欢的项目:
select top (10)
ItemID, sum(ToLikeOrNotLike)
from Items
group by ItemID
order by sum(ToLikeOrNotLike) desc;
这也解决了相互排斥问题。
根据Spevy的建议(参见评论), 0 (不喜欢或不喜欢)可以替换为 null ,这样更容易确定项目的整体活动。例如:
select top (10)
ItemID, count(ToLikeOrNotLike)
from Items
group by ItemID
order by count(ToLikeOrNotLike) desc;
会返回有多少喜欢或不喜欢收到的商品。这可以用于区分具有2个喜欢和1个不喜欢的项目,以及具有10,000个喜欢和9,999个不喜欢的项目,这两者在总结时都是无法区分的。
答案 1 :(得分:0)
这是基于您对表的第一个想法,该表具有布尔列,用于针对该项目执行的单独操作。
在表格上使用CHECK
约束(将表名更改为您的表名称的任何名称):
ALTER TABLE UserAction
ADD CONSTRAINT CK_LikeOrDisLike
CHECK (
(Like is null AND Dislike is null)
OR (Like = 1 AND Dislike is null)
OR (Like is null AND Dislike = 1)
)
或者也许:
ALTER TABLE UserAction
ADD CONSTRAINT CK_LikeOrDisLike
CHECK (
(ISNULL(Like, 0) = 0 AND ISNULL(Dislike, 0) = 0)
OR (Like = 1 AND ISNULL(Dislike, 0) = 0)
OR (ISNULL(Like, 0) = 0 AND Dislike = 1)
)
除了0 = false
之外,还要允许null = false
。
然后可以进一步改为:
ALTER TABLE UserAction
ADD CONSTRAINT CK_LikeOrDisLike
CHECK (
ISNULL(Like, 0) = 0 OR ISNULL(Dislike, 0) = 0
)
最后一个意味着Like
和Dislike
中至少有一个必须为false或null。
这当然不能帮助您从程序中进行一致的更新,您仍然必须单独处理。但 IF 您的程序尝试进行无效的插入或更新,数据库将拒绝它并显示错误消息。