【问题标题】:Mysql keep track of user likes and dislikesMysql 跟踪用户的好恶
【发布时间】:2011-05-15 23:16:19
【问题描述】:

我正在创建一个公告板应用程序。每个公告都可以被网站的用户喜欢或不喜欢。为了跟踪喜欢和不喜欢的情况,我创建了以下数据库表

id  user_id   bulletin_id   like_dislike
1   1         1             1
2   1         2             0
3   3         1             1
4   2         1             0

like_dislike 列中,1 表示“喜欢”,0 表示“不喜欢” 我知道怎么问。 - 公告 1 被点赞了多少次 (2) - 公告 1 被不喜欢多少次 (1)

但是我如何进行查询以同时提出这两个问题?也就是说,公告 1 被喜欢和不喜欢多少次

liked  disliked
2      1

我已经尝试过查询

  SELECT count(like_dislike) AS likes, count(like_dislike) AS dislikes FROM bulletins_ld
where bulletins_id = 1 AND likes = 1 AND dislikes = 0

但我得到的只是两次,这并不奇怪。
我能想到的唯一解决方案是有一个单独的喜欢和不喜欢列

【问题讨论】:

    标签: php mysql normalization


    【解决方案1】:

    您可以通过聚合查询来执行此操作,在单个 like_dislike 列上使用相反的条件(我在下面假设该列中的“1”表示“喜欢”)。

    SELECT bulletin_id, 
           SUM(CASE WHEN like_dislike = 1 THEN 1 ELSE 0 END) AS likes, 
           SUM(CASE WHEN like_dislike = 0 THEN 1 ELSE 0 END) AS dislikes
    FROM bulletins_ld
    GROUP BY bulletin_id
    

    更新:根据下面 cmets 中的讨论,可以将喜欢/不喜欢列标准化为自己的表,就像这样(故意愚蠢的示例......):

    CREATE TABLE how_user_feels(
        feeling_id INT,
        feeling_desc VARCHAR(20)
    )
    
    INSERT INTO how_user_feels(feeling_id, feeling_desc) VALUES
    (0, 'Undecided'),
    (1, 'Likes It'),
    (2, 'Could Do Without It')
    

    然后,Bulletin 表中的 Likes_Dislikes 列将替换为外键 feeling_id,默认为 0。假设您随后在用户第一次查看公告时在此表中输入一条记录,使他们“未决定” "默认情况下,并在他们对公告投票时更新该记录。您可以像这样查询结果:

    SELECT bulletin_id, 
           SUM(CASE WHEN feelings_id = 1 THEN 1 ELSE 0 END) AS likes, 
           SUM(CASE WHEN feelings_id = 2 THEN 1 ELSE 0 END) AS dislikes,
           SUM(CASE WHEN feelings_id = 0 THEN 1 ELSE 0 END) AS doesnt_seem_to_care
    FROM bulletins_ld b
    INNER JOIN how_user_feels h ON b.feeling_id = h.feeling_id
    GROUP BY bulletin_id
    

    请记住,这只是一种方法,可能对您的情况没有用。但是,如果您决定更改扩展用户表达他们对公告的感受的模型,例如五星级评级系统,那么您可以做到这一点,而无需更改数据库架构 - 只需更改 how_user_feels 表中的记录以及相关查询。

    【讨论】:

    • @djacobson。您可以删除 INNER JOIN how_user_feels h ON b.feeling_id = h.feeling_id 它对结果集没有任何作用(您没有从 h 得到任何东西),它会损害性能。
    【解决方案2】:

    这个查询对我有用:

    SELECT bulletin_id, 
        sum(like_dislike) AS likes, 
        sum((1-like_dislike)) AS dislikes 
    FROM bulletins_ld 
        GROUP BY (bulletin_id);
    

    这假设 likedislike = 1 表示“喜欢”,likedislike = 0 表示“不喜欢”。

    ID    LIKES    DISLIKES
    1     2    1
    2     0    1
    

    【讨论】:

      【解决方案3】:
      1. 为了记录,还有另一种方法可以获得相同的结果集,是更快还是更慢取决于平台。这使用标量子查询而不是外部查询的聚合。这个想法是,如果您从集合的角度考虑,这应该会更容易。或者就维度事实而言。

        首先,我们必须整理您的姓名。让我们称您的“表”为bulletin_like 和主公告表bulletinbulletin_id 对它们中的任何一个来说都是一个非常愚蠢的名称,这更像是一个列名)。只需调用布尔列like(如果为1,like 为真;如果为0,like 为假;这就是布尔的含义)。使用单数形式的名称。

        SELECT name AS bulletin, 
            (SELECT COUNT(like) 
                FROM  bulletin_like bl 
                WHERE bl.bulletin_id = b.bulletin_id 
                AND   like = 1
                ) AS like,
            (SELECT COUNT(like) 
                FROM  bulletin_like bl 
                WHERE bl.bulletin_id = b.bulletin_id 
                AND   like = 0
                ) AS dislike
        FROM bulletin b
      2. 您要求提供标准化标签。 bulletin_like "table" 没有被规范化。去掉Idiot 列,它除了冗余列和附加索引之外没有其他用途。 PK 是(bulletin_id, user_id)

        除非您希望用户在每个公告的每个海报上发布多个喜欢和不喜欢的内容。

      【讨论】:

        猜你喜欢
        • 2014-09-18
        • 2016-11-11
        • 2010-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-05
        相关资源
        最近更新 更多