1

我有以下 SQL 查询:

SELECT tblBooks.bookID,
    tblBooks.title,
    tblBooks.author,
    tblBooks.coverImage,
    ROUND(ROUND(tblReviews.rating * 2) / 2, 1) AS rating
FROM tblBooks
    LEFT JOIN tblReviews
        ON tblBooks.bookID = tblReviews.bookID
        LEFT JOIN tblMembers
            ON tblReviews.userID = tblMembers.userID
WHERE tblReviews.bookID IS NOT NULL
ORDER BY rating DESC
LIMIT 0, 40

我想查询数据库并返回平均评分,因此,如果一本书已被审查 6 次,则将 6 个用户的每个评分相加并计算平均值。现在只返回最新的评级。当我将此行更改为:

ROUND(ROUND(AVG(tblReviews.rating) * 2) / 2, 1) AS rating

总共只返回一个结果,所以显然有问题,但我不知道是什么。

如果有人能对此有所了解,我认为这与我的加入有关。

4

5 回答 5

3

你需要使用group by这样的:

SELECT tblBooks.bookID, tblBooks.title, tblBooks.author, tblBooks.coverImage,
       AVG(tblReviews.rating) as avgRating
FROM tblBooks
     LEFT JOIN tblReviews
     ON tblBooks.bookID = tblReviews.bookID
WHERE tblReviews.bookID IS NOT NULL
group by tblBooks.bookID, tblBooks.title, tblBooks.author, tblBooks.coverImage
ORDER BY avgrating DESC

您的查询似乎没有使用 Members 表中的任何信息,因此我将其删除。它甚至没有基于它进行过滤,因为您使用的是left join.

于 2013-04-18T17:38:34.680 回答
1

为什么不AVG改用?

SELECT tblBooks.bookID,
    tblBooks.title,
    tblBooks.author,
    tblBooks.coverImage,
    AVG(tblReviews.rating) AS rating
FROM tblBooks
    LEFT JOIN tblReviews
        ON tblBooks.bookID = tblReviews.bookID
        LEFT JOIN tblMembers
            ON tblReviews.userID = tblMembers.userID
WHERE tblReviews.bookID IS NOT NULL
Group By tblBooks.bookID, tblBooks.title, tblBooks.author, tblBooks.coverImage
ORDER BY rating DESC
LIMIT 0, 40

供参考

在 MYSQL 中,您不需要按所有列进行分组,尽管这是一个很好的做法,因为在使用其他 RDMS 时您将需要这样做。

于 2013-04-18T17:39:55.403 回答
1

你也不需要WHERE。您实际上是在进行INNER联接:

SELECT t.bookID,
       t.title,
       t.author,
       t.coverImage,
       AVG(r.rating) AS rating
FROM tblBooks AS t
    JOIN tblReviews AS r
        ON b.bookID = r.bookID
GROUP BY t.bookID
--     , t.title, t.author, t.coverImage 
ORDER BY rating DESC
LIMIT 40 ;

注意:仅使用GROUP BY t.bookID(并且没有其他列)只有bookIDtblBooks. 所有其他 DBMS 都不允许这样做(Postgres 除外,但该产品已正确实现了该功能,并且它确实检查其他列是否依赖于分组列)。MySQL 根本不进行检查,因此在很多情况下它会给出错误的结果。

这也取决于sql_mode设置,上面是否会正常运行。


您也可以先分组,然后加入。这是有效的 SQL,不会出现错误结果:

SELECT t.bookID,
       t.title,
       t.author,
       t.coverImage,
       g.rating
FROM tblBooks AS t
    JOIN 
        ( SELECT r.bookID,
                 AVG(r.rating) AS rating
          FROM tblReviews AS r
          GROUP BY r.bookID
        ) AS g
        ON b.bookID = r.bookID
ORDER BY rating DESC
LIMIT 40 ;
于 2013-04-18T17:49:57.533 回答
0

我认为你缺少的是

 GROUP BY tblBooks.bookID, tblBooks.title, tblBooks.author, etc...

AVG 是一个汇总数据的聚合函数,使用 GROUP BY 创建聚合组。

于 2013-04-18T17:35:49.187 回答
0

试试这个:

...
WHERE tblReviews.bookID IS NOT NULL
GROUP BY tblBooks.bookID
ORDER BY rating DESC
LIMIT 0, 40

干杯。

于 2013-04-18T17:36:16.573 回答