如何在表中存储互斥值

时间:2014-09-19 10:42:08

标签: sql sql-server sql-server-2012

根据社交网络设计,我需要存储某人是否有LikedDisliked。他们还可以采取其他行动,例如Share

我需要做的是确保当一个人Like某事时,其值存储为true。但如果他们改变主意并Dislike同样的事情,则Like'd值设置为NULLDislike值设置为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'然后我必须将这些列添加到表中。这打破了规范化规则,但它可以工作。重要的商业规则是,某人不能LikeDislike同时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操作覆盖

任何人都可以建议最好的方法是什么?它是导致我最烦的某些行为之间的相互排他性。

2 个答案:

答案 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
)

最后一个意味着LikeDislike中至少有一个必须为false或null。

这当然不能帮助您从程序中进行一致的更新,您仍然必须单独处理。但 IF 您的程序尝试进​​行无效的插入或更新,数据库将拒绝它并显示错误消息。