开发者

Help with SQL join

I have 3 tables a) BOOKS (id,name) b) RATINGS (book id,rating,ip address) c) comments (comment_id,book id,comments,date)

I want to show开发者_开发技巧 BOOK NAME,RATING,Number of COMMENTS using left join.

The issue with my query is it shows different ratings if the number of comments changes.

For example if there is one comment for a book the data returned by sql is perfect but the moment more comments are added the rating appears incorrect.

SELECT
    book.id,
    book.name,SUM( rtng.rating ) As total_rating,
    COUNT(distinct cmt.comment_id ) AS comment_count
FROM books book
    LEFT JOIN ratings rtng ON rtng.book_id = book.id
    LEFT JOIN comments cmt ON cmt.book_id = book.id


This way, you can get ALL books regardless of any missing a rating or comment... The primary table is books then do left join to each comment and rating respectively.

select
      B.ID,
      B.Name,
      COALESCE( TR.Rating, 0 ) TotalRating,
      COALESCE( TR.AvgRating, 0 ) AvgRating,
      COALESCE( COM.CommentCnt, 0 ) TotalComents
   FROM
      Books B
         LEFT JOIN ( select R.Book_ID,
                            SUM( R.Rating ) Rating,
                            AVG( R.Rating ) AvgRating
                        FROM Ratings R
                        Group By R.Book_ID ) TR
            ON B.ID = TR.Book_ID

         LEFT JOIN ( select C.Book_ID, 
                            count(*) CommentCnt
                        FROM Comments C
                        Group by C.Book_ID ) COM
            ON B.ID = COM.Book_ID


This likely has to do with the fact that the relationship between the books table and the comments (and ratings) tables is "one to many". You're going to have to do at least two queries:

(pseudocode follows)

all_book_ids = SELECT book_id FROM books

foreach a_single_book in all_book_ids
    SELECT * FROM comments WHERE book_id = a_single_book
    SELECT * FROM ratings  WHERE book_id = a_single_book


How about grouping based in books ID and additionally computing the average rating?

SELECT book.id,
       book.name,
       SUM( rtng.rating )              AS total_rating
       AVG( rtng.rating )              AS averageRating,
       COUNT(distinct cmt.comment_id ) AS comment_count
  FROM books                           AS book
  LEFT JOIN ratings rtng 
         ON rtng.book_id = book.id
  LEFT JOIN comments cmt 
         ON cmt.book_id = book.id    
  GROUP BY book.id


one more

SELECT book.id,book.name,
rtng.total_rating,
cmt.comment_count
from books book 
LEFT JOIN 
(
select book.id,book.name, SUM( rtng.rating ) As total_rating
from books book
inner join ratings rtng 
ON rtng.book_id = book.id 
group by book.id,book.name
)rtng 
ON rtng.book_id = book.id 

LEFT JOIN 
(
select book.id,book.name, COUNT(*) AS comment_count 
from books book
    left join comments cmt 
    ON cmt.book_id = book.id
group by book.id,book.name
)cmt 
ON cmt.book_id = book.id
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜