这个SQL有什么问题

时间:2013-04-18 17:32:19

标签: mysql sql

我有以下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

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

如果有人能说清楚这一点,我认为这会与我的联系有关。

5 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

FYI

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

答案 2 :(得分: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.bookIDbookID中的主键(或具有唯一约束)时,仅使用tblBooks(并且不存在其他列)才会给出正确的结果。所有其他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 ;

答案 3 :(得分:0)

我认为你缺少的是

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

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

答案 4 :(得分:0)

试试这个:

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

干杯。