【问题标题】:MySQL AVG() return 0 if NULLMySQL AVG() 如果为 NULL,则返回 0
【发布时间】:2015-11-30 02:01:18
【问题描述】:

我有 3 个表,如下所示:

mysql> select * from Raccoon;
+----+------------------+----------------------------------------------------------------------------------------------------+
| id | name             | image_url                                                                                          |
+----+------------------+----------------------------------------------------------------------------------------------------+
|  3 | Jesse Coon James | http://www.pawfun.com/wp/wp-content/uploads/2010/01/rabbid.png                                     |
|  4 | Bobby Coon       | https://c2.staticflickr.com/6/5242/5370143072_dee60d0ce2_n.jpg                                     |
|  5 | Doc Raccoon      | http://images.encyclopedia.com/utility/image.aspx?id=2801690&imagetype=Manual&height=300&width=300 |
|  6 | Eddie the Rac    | http://www.felid.org/jpg/EDDIE%20THE%20RACCOON.jpg                                                 |
+----+------------------+----------------------------------------------------------------------------------------------------+
4 rows in set (0.00 sec)

mysql> select * from Review;
+----+------------+-------------+---------------------------------------------+--------+
| id | raccoon_id | reviewer_id | review                                      | rating |
+----+------------+-------------+---------------------------------------------+--------+
|  1 |          3 |           1 | This raccoon was a fine raccoon indeed.     |      5 |
|  2 |          5 |           2 | This raccoon did not do much for me at all. |      2 |
|  3 |          3 |           1 | asdfsadfsadf                                |      5 |
|  4 |          5 |           2 | asdfsadf                                    |      1 |
+----+------------+-------------+---------------------------------------------+--------+
4 rows in set (0.00 sec)

mysql> select * from Reviewer;
+----+---------------+
| id | reviewer_name |
+----+---------------+
|  1 | Kane Charles  |
|  2 | Cameron Foale |
+----+---------------+
2 rows in set (0.00 sec)

我正在尝试构建一个选择查询,该查询将返回 Raccoon 中的所有列以及一个额外的列,该列获取平均 Review.rating(按 id 分组)。我面临的问题是,不能保证Review 表中每个 Raccoon 都会存在行(由 FK 确定,raccoon_id 引用Raccoon.id。在存在零行的情况下在 Review 表中(对于给定的 Raccoon.id,即 Review.raccoon_id),我希望查询返回 0 作为该 Raccoon 的平均值。

以下是我正在使用的当前查询:

mysql> SELECT *, (SELECT IFNULL(AVG(rating),0) FROM Review WHERE raccoon_id=Raccoon.id GROUP BY raccoon_id) AS "AVG" FROM Raccoon ORDER BY "AVG" ASC;
+----+------------------+----------------------------------------------------------------------------------------------------+--------+
| id | name             | image_url                                                                                          | AVG    |
+----+------------------+----------------------------------------------------------------------------------------------------+--------+
|  3 | Jesse Coon James | http://www.pawfun.com/wp/wp-content/uploads/2010/01/rabbid.png                                     | 5.0000 |
|  4 | Bobby Coon       | https://c2.staticflickr.com/6/5242/5370143072_dee60d0ce2_n.jpg                                     |   NULL |
|  5 | Doc Raccoon      | http://images.encyclopedia.com/utility/image.aspx?id=2801690&imagetype=Manual&height=300&width=300 | 1.5000 |
|  6 | Eddie the Rac    | http://www.felid.org/jpg/EDDIE%20THE%20RACCOON.jpg                                                 |   NULL |
+----+------------------+----------------------------------------------------------------------------------------------------+--------+
4 rows in set (0.00 sec)

正如您在上面看到的,对于 ID 为 4 和 6 的 Raccoons,查询没有返回 0,它只是返回 NULL。我需要它返回如下内容(注意排序,首先按最低平均评论排序):

+----+------------------+----------------------------------------------------------------------------------------------------+--------+
| id | name             | image_url                                                                                          | AVG    |
+----+------------------+----------------------------------------------------------------------------------------------------+--------+
|  4 | Bobby Coon       | https://c2.staticflickr.com/6/5242/5370143072_dee60d0ce2_n.jpg                                     | 0.0000 |
|  6 | Eddie the Rac    | http://www.felid.org/jpg/EDDIE%20THE%20RACCOON.jpg                                                 | 0.0000 |
|  5 | Doc Raccoon      | http://images.encyclopedia.com/utility/image.aspx?id=2801690&imagetype=Manual&height=300&width=300 | 1.5000 |
|  3 | Jesse Coon James | http://www.pawfun.com/wp/wp-content/uploads/2010/01/rabbid.png                                     | 5.0000 |
+----+------------------+----------------------------------------------------------------------------------------------------+--------+

【问题讨论】:

    标签: mysql sql if-statement null average


    【解决方案1】:

    在子查询之外使用IFNULL,因为如果外部表不匹配,它将返回 null,

    IFNULL((SELECT AVG(rating) FROM Review WHERE raccoon_id=Raccoon.id GROUP BY raccoon_id), 0) AS "AVG"
    

    或者你也可以使用LEFT JOIN

    SELECT  ra.id, ra.name, ra.image_url,
            IFNULL(AVG(rv.rating),0)AS "AVG" 
    FROM    Raccoon ra
            LEFT JOIN Review rv
                ON rv.raccoon_id = ra.id
    GROUP   BY ra.id, ra.name, ra.image_url  
    ORDER   BY "AVG" ASC;
    

    【讨论】:

      【解决方案2】:

      您不想在子查询中使用group by。这很危险,因为它可能返回多行(尽管where 阻止了这种情况)。更重要的是,没有group by,子查询是一个总是返回一行的聚合查询。所以,你可以把逻辑放在子查询中:

      SELECT r.*,
             (SELECT COALESCE(AVG(rev.rating),0)
              FROM Review rev
              WHERE rev.raccoon_id = r.id
             ) AS "AVG"
      FROM Raccoon r
      ORDER BY "AVG" ASC;
      

      另外:当您有相关子查询时,请始终使用限定列名。这是防止将来出现问题的好习惯。

      【讨论】:

        【解决方案3】:

        您可以使用内置函数 COALESCE() 尝试以下 SQL 语句:

        SELECT *,  COALESCE((SELECT AVG(rating) FROM Review WHERE raccoon_id=Raccoon.id GROUP BY raccoon_id), 0) AS "AVG" FROM Raccoon ORDER BY "AVG" ASC;
        

        你可以找到这个函数的使用手册here

        如果你更喜欢使用 IFNULL,你可以使用

        SELECT *, IFNULL((SELECT AVG(rating) FROM Review WHERE raccoon_id=Raccoon.id GROUP BY raccoon_id), 0) AS "AVG" FROM Raccoon ORDER BY "AVG" ASC;
        

        您似乎误解了函数的范围。

        但是,我认为更好的方法是使用左外连接,而不是子查询,这是我写的查询供您参考:

        select Raccoon.id, Raccoon.name, Raccoon.image_url, IFNULL(AVG(rating),0) avg from Raccoon LEFT OUTER join Review ON raccoon_id =Raccoon.id GROUP BY raccoon.id ORDER BY AVG ASC;
        

        然后你会得到以下结果:

        (对不起,我不知道如何发布此查询的输出,然后我截取了屏幕截图 :-)

        希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-05
          • 2018-07-30
          • 2012-06-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多