SQL查询、AVG和COUNT在多个表上

时间:2021-02-13 00:55:23

I need a query, the query that i used doesn't work the way i want for some reason

我需要一个查询,由于某些原因,我使用的查询不能以我想要的方式工作

Here's all the tables involved in the query.

下面是查询中涉及的所有表。

SQL查询、AVG和COUNT在多个表上

Here's the query i want : Show a list of books with their average ratings and its number of recommendations

下面是我想要的查询:显示一份图书列表,列出它们的平均评级和推荐数量

result should be like this : SQL查询、AVG和COUNT在多个表上

结果应该是这样的:

What i already tried :

我已经尝试过的:

SELECT        book.isbn, AVG(ratings.rating) AS [AVG Ratings], COUNT(recommend.isbn) AS [Number of recommendation]
FROM            book INNER JOIN
                         recommend ON book.isbn = recommend.isbn INNER JOIN
                         ratings ON book.isbn = ratings.isbn
GROUP BY book.isbn

But it didn't work, somehow the the AVG rating works great, but the # of recommendations does not, it conflicts with the ratings table.

但是它不起作用,AVG的评级工作得很好,但是推荐的#没有,它与评级表相冲突。

here's what the result is:

结果是:

SQL查询、AVG和COUNT在多个表上

However when i try each one alone, everything works great like this :

然而,当我独自一人尝试时,一切都很好:

for AVG ratings :

AVG评级:

SELECT        book.isbn, AVG(ratings.rating) AS [AVG Ratings]
FROM            book INNER JOIN
                         ratings ON book.isbn = ratings.isbn
GROUP BY book.isbn

Here's the result :

结果:

SQL查询、AVG和COUNT在多个表上

And for the # of recommendations :

关于建议的#:

SELECT        book.isbn, COUNT(recommend.isbn) AS [Number of recommendation]
FROM            book INNER JOIN
                         recommend ON book.isbn = recommend.isbn
GROUP BY book.isbn

Here's the result :

结果:

SQL查询、AVG和COUNT在多个表上

So i want a query to combine the two views into one view

因此,我希望查询将两个视图合并到一个视图中。

4 个解决方案

#1


1  

Well, you could combine the two views into one..

你可以把这两种观点合并成一种。

Here, this should work the way you want

在这里,这应该是你想要的方式

SELECT l.isbn, v.rating, r.rec
FROM book l, 
    (SELECT isbn, AVG(rating) AS rating FROM ratings GROUP BY isbn) v,
    (SELECT isbn, COUNT(isbn) AS rec FROM recommend GROUP BY isbn) r
WHERE l.isbn=v.isbn AND l.isbn=r.isbn

Hope this helps.

希望这个有帮助。

Best regards!

最好的问候!

#2


2  

If you want to get accurate results, then you need to do the aggregations before the join:

如果您想获得准确的结果,那么您需要在连接之前进行聚合:

SELECT b.isbn, r.AvgRating, re.NumRecommendation
FROM  book b LEFT JOIN
      (SELECT r.isbn, AVG(r.rating) as AvgRating
       FROM rating r
       GROUP BY r.isbn
      ) r
      ON b.isbn = r.isbn LEFT JOIN
      (SELECT r.isbn, COUNT(*) as NumRecommendation
       FROM recommendation r
       GROUP BY r.isbn
      ) re
      on b.isbn = r.isbn ;

Note that I also switched to left outer joins, so you will get results for all books, even those that are missing either ratings or recommendations.

注意,我还切换到左外连接,因此您将获得所有图书的结果,即使是那些没有评级或推荐的图书。

#3


0  

SELECT 
  book.isbn, 
  IFNULL(AVG(ratings.rating),"Not yet rated") AS [AVG Ratings],
  IFNULL(COUNT(DISTINCT recommend.iduse),0) AS [Number of recommendation]
FROM
  book
  LEFT JOIN recommend ON book.isbn = recommend.isbn 
  LEFT JOIN ratings ON book.isbn = ratings.isbn
GROUP BY book.isbn

Should to the trick:

应的诀窍:

  • Counting the distinct users recommending a book will fix the cartesian product issue
  • 计算推荐一本书的不同用户将解决笛卡尔产品的问题
  • Left joins with the usual IFNULL() plumbing will make it work on books that have either no recommendations or no ratings
  • 使用常规的IFNULL()管道将使它在没有推荐或没有评级的书籍上工作

#4


0  

If you are using SQL Server you can use the over clause:

如果您正在使用SQL Server,您可以使用over子句:

SELECT 
  B.isbn, 
  AVG(ra.rating) OVER (PARTITION BY B.isbn) AS [AVG RATE],
  COUNT(re.isbn) OVER (PARTITION BY B.isbn) AS [RECOMMEND COUNT]
FROM Book B
LEFT JOIN recommend re ON B.isbn = re.isbn 
LEFT JOIN ratings ra ON B.isbn = ra.isbn

#1


1  

Well, you could combine the two views into one..

你可以把这两种观点合并成一种。

Here, this should work the way you want

在这里,这应该是你想要的方式

SELECT l.isbn, v.rating, r.rec
FROM book l, 
    (SELECT isbn, AVG(rating) AS rating FROM ratings GROUP BY isbn) v,
    (SELECT isbn, COUNT(isbn) AS rec FROM recommend GROUP BY isbn) r
WHERE l.isbn=v.isbn AND l.isbn=r.isbn

Hope this helps.

希望这个有帮助。

Best regards!

最好的问候!

#2


2  

If you want to get accurate results, then you need to do the aggregations before the join:

如果您想获得准确的结果,那么您需要在连接之前进行聚合:

SELECT b.isbn, r.AvgRating, re.NumRecommendation
FROM  book b LEFT JOIN
      (SELECT r.isbn, AVG(r.rating) as AvgRating
       FROM rating r
       GROUP BY r.isbn
      ) r
      ON b.isbn = r.isbn LEFT JOIN
      (SELECT r.isbn, COUNT(*) as NumRecommendation
       FROM recommendation r
       GROUP BY r.isbn
      ) re
      on b.isbn = r.isbn ;

Note that I also switched to left outer joins, so you will get results for all books, even those that are missing either ratings or recommendations.

注意,我还切换到左外连接,因此您将获得所有图书的结果,即使是那些没有评级或推荐的图书。

#3


0  

SELECT 
  book.isbn, 
  IFNULL(AVG(ratings.rating),"Not yet rated") AS [AVG Ratings],
  IFNULL(COUNT(DISTINCT recommend.iduse),0) AS [Number of recommendation]
FROM
  book
  LEFT JOIN recommend ON book.isbn = recommend.isbn 
  LEFT JOIN ratings ON book.isbn = ratings.isbn
GROUP BY book.isbn

Should to the trick:

应的诀窍:

  • Counting the distinct users recommending a book will fix the cartesian product issue
  • 计算推荐一本书的不同用户将解决笛卡尔产品的问题
  • Left joins with the usual IFNULL() plumbing will make it work on books that have either no recommendations or no ratings
  • 使用常规的IFNULL()管道将使它在没有推荐或没有评级的书籍上工作

#4


0  

If you are using SQL Server you can use the over clause:

如果您正在使用SQL Server,您可以使用over子句:

SELECT 
  B.isbn, 
  AVG(ra.rating) OVER (PARTITION BY B.isbn) AS [AVG RATE],
  COUNT(re.isbn) OVER (PARTITION BY B.isbn) AS [RECOMMEND COUNT]
FROM Book B
LEFT JOIN recommend re ON B.isbn = re.isbn 
LEFT JOIN ratings ra ON B.isbn = ra.isbn