2013-04-18 3 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, вам не нужно сгруппировать по все колоннам, хотя все это хорошая практика, потому что вы должны при использовании другой RDMS.

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. Все остальные СУБД этого не допускают (кроме 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 Очень подробно. –

Смежные вопросы