2013-04-18 51 views
0

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

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

如果任何人都可以对此有所了解,我认为这将与我的加入有关。

+1

您不能混合聚合函数和常规列选择。您需要进行分组以获得该结果或使用子查询 –

回答

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 

您的查询似乎不使用从成员表中的任何信息,所以我淘汰了。它甚至不基于它进行过滤,因为您使用的是left join

+0

我在另一个查询中从成员表中获取信息,即谁查看过它。但谢谢你现在指出。 – Mike

0

我认为你缺少的是

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

AVG是一个聚合函数,总结出的数据,使用GROUP BY创建聚集的群体。

+0

该组由哪里去? – Mike

+0

http://www.databasechannel.com/AccessArticles/Article_Select_GroupByHaving.html – RandomUs1r

0

试试这个:

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

干杯。

+0

为什么要投哥们? –

+0

因为如果按1列进行分组,则无法选择不在组中的其他人。那么,MySQL允许有意想不到的结果。 –

+0

@juergend在这种情况下,结果不会是意料之外的。他由该表的PK组成,只显示该表的列。 –

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中,你没有全部虽然这是一个很好的做法,因为你需要使用其他关系数据库管理系统时,需要按所有列。

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(并且没有其他列在那里)会给出正确的结果只有bookID是主键(或具有唯一约束)在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 ; 
+0

+1非常详细。 –