【问题标题】:MySql selecting default value if there are no results?如果没有结果,MySql 选择默认值?
【发布时间】:2010-05-27 15:49:26
【问题描述】:

我有 2 张桌子:会员和 cmets。 我选择所有成员,然后加入 cmets。 但是在 cmets 中,我选择了一些点的总和,如果用户从未发表过评论,我无法让该用户出现在列表中?!

如果用户从未评论过,如何将 SUM 的默认值选择为 0,或其他解决方案:

SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
            SUM(c.vote_value) AS vote_value, SUM(c.best) AS best, 
            SUM(c.vote_value) + SUM(c.best)*10 AS total
            FROM members m
            LEFT JOIN comments c ON m.member_id = c.author_id
            GROUP BY c.author_id
            ORDER BY m.member_id DESC
            LIMIT 0, 20

编辑:

我会尽力解释... 所以有2个表,成员和cmets。我需要列出所有用户的排名。 评论拥有所有投票和最佳答案。

所以,我需要列出所有用户,然后他们得分。

成员表:

member_id - username - avatar

评论表

comment_id - author_id - vote_value - best (0 OR 1)

也尝试从 COMMENTS 中选择并加入 MEMBERS,但又是同样的事情:(

【问题讨论】:

  • 您能否提供一些具有预期输出的示例数据?我不使用 MySQL,所以也许他们有一些快捷语法,但你只在一个列上进行 GROUPing,但在你的 SELECT 中有几个非聚合列
  • @Tom H.:MySQL 实际上允许这种语法:GROUP BY and HAVING with Hidden Columns
  • 谢谢彼得。我知道至少有一个主要的 RDBMS 允许这样做,但不记得是哪个。因为它允许“不合逻辑”的分组,但它可能导致“丢失”数据,因为“使用此功能时,每个组中的所有行都应该具有相同的值,用于从 GROUP BY 部分省略的列。服务器是免费的从组中返回任何值,因此除非所有值都相同,否则结果是不确定的。”对于给定的 c.author_id,c.comment_id 可能并不总是相同
  • 我用表格结构编辑了我的问题,也许它有助于更​​好地理解。谢谢
  • 尝试分解您的查询并重新构建它,看看是什么部分破坏了它。从“SELECT m.member_id, SUM(c.vote_value) FROM ...”开始以确保它有效,然后一次添加其他 SUM 和列以找出问题。

标签: mysql


【解决方案1】:

如果您只想要用户和他们的排名,我不确定为什么要将 comment_id 包含在您的 SELECT 列表中。您只想要他们对该特定评论的排名吗?我现在给出一个解决方案,假设您只想要一个完整的成员列表和排名:

SELECT
    M.member_id,
    M.user_id,
    M.avatar,
    COALESCE(SUM(C.vote_value), 0) AS vote_value_sum,
    COALESCE(SUM(C.best), 0) AS best_sum,
    COALESCE(SUM(C.vote_value), 0) + SUM(C.best) * 10 AS total_value
FROM
    Members M
LEFT OUTER JOIN Comments C ON
    C.author_id = M.member_id
GROUP BY
    M.member_id
ORDER BY
    total_value DESC
LIMIT 0, 20

(假设 vote_value 和 best 不是 NULL 列,或者 MySQL 在计算 SUM 值时会忽略这些列 - 我相信确实如此,但我还没有测试过)

【讨论】:

    【解决方案2】:

    MySQL 有一个 IFNULL 运算符,如果结果为 null,则允许您返回 null 以外的值。

    SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
                SUM(IFNULL(c.vote_value, 0)) AS vote_value, SUM(IFNULL(c.best, 0)) AS best, 
                SUM(IFNULL(c.vote_value, 0)) + SUM(IFNULL(c.best, 0))*10 AS total
                FROM members m
                LEFT JOIN comments c ON m.member_id = c.author_id
                GROUP BY c.author_id
                ORDER BY m.member_id DESC
                LIMIT 0, 20
    

    正如其他人提到的,COALESCE 做了类似的事情(也适用于 MySQL)。

    【讨论】:

    • 在需要默认值的情况下,这可能比COALESCE 好一点。
    • 也没有列表中的所有用户:\
    • 那么@nathan 很可能是正确的。尝试在 m.member_id 而不是 c.author_id 上进行分组,看看是否有帮助。
    • 仍然没有 :( 我用表格和结构编辑了我的问题,也许会有所帮助,谢谢
    【解决方案3】:

    我使用COALESCE 来处理这类事情。

    http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html#function_coalesce

    我会将你的第二行和第三行改写为:

    COALESCE(SUM(c.vote_value), 0) AS vote_value, COALESCE(SUM(c.best),0) AS best,
    COALESCE(SUM(c.vote_value), 0) + COALESCE(SUM(c.best),0) * 10 AS total
    

    【讨论】:

      【解决方案4】:

      我认为 SUM 不是问题。我想这可能是你的

      GROUP BY c.author_id
      

      您按左外连接的右侧进行分组的位置。我不确定当右侧不存在时会发生什么,但我猜这不是你真正想要的。您很可能应该按成员中的某些内容进行分组,而不是 cmets。

      话虽如此,是的,您还应该使用 COALESCE 或 IFNULL 将空值变为 0。

      【讨论】:

      • 尝试分组 m.member_id 但仍然相同,并非列表中的所有用户。我用表格结构编辑了我的问题,也许它有助于更​​好地理解。谢谢
      • 尝试分解您的查询并重新构建它,看看是什么部分破坏了它。从“SELECT m.member_id, SUM(c.vote_value) FROM ...”开始以确保它有效,然后一次添加其他 SUM 和列以找出问题。
      【解决方案5】:

      您可以使用 if 语句将 NULL 转换为 0

      SELECT c.comment_id AS item_id, ...
          IF(SUM(c.vote_value) is null, 0, SUM(c.vote_value)) as vote_value
      FROM members m
      LEFT JOIN comments c ON ...
      

      【讨论】:

      • COALESCE 做同样的事情,但更简单。 SUM(COALESCE(c.vote_value, 0))
      • 这是一个笨重的机制。 IF (x is NULL, y, x) 不是很整洁。
      • @nathan: 以前不知道,只是用过而已。谢谢(顺便说一句。我不得不使用 COALESCE(SUM(col), 0) 因为反过来仍然返回 null。
      【解决方案6】:

      您也可以查看 CASE 声明:http://dev.mysql.com/doc/refman/5.0/en/case-statement.html

      在您的情况下,结果将类似于...

      SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
              (CASE SUM(c.vote_value) WHEN NULL THEN 0  
              ELSE SUM(c.vote_value) END) AS vote_value, SUM(c.best) AS best, 
              (CASE SUM(c.vote_value) + SUM(c.najbolji)*10 WHEN null THEN 0
              ELSE SUM(c.vote_value) + SUM(c.najbolji)*10 END) AS total
              FROM members m
              LEFT JOIN comments c ON m.member_id = c.author_id
              GROUP BY c.author_id
              ORDER BY m.member_id DESC
              LIMIT 0, 20
      

      【讨论】:

      • 不幸的是,这太笨拙了。
      猜你喜欢
      • 1970-01-01
      • 2020-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-29
      • 1970-01-01
      相关资源
      最近更新 更多