Find the max average for each country - SQL SERVER - sql

For each country, report the book with the highest average rating. If two or more books have the same average rating, report the one with the highest number of ratings. If two or more books are still tie (same highest average rating and same number of ratings), report them all sorted alphabetically on book title. If a country is not associated to any ratings, it should not show up in the query output.
myTablesSample
SELECT CountryName, Title, AVG(CAST(Rate AS DECIMAL)) as AverageRatePerCountry, count(Rate) as NumberOfRates
FROM bda.booksRatings as BR2
left JOIN bda.books as B2 on B2.ISBN = BR2.ISBN
left JOIN bda.users as U2 ON U2.UserID = BR2.UserID
left JOIN bda.countries as C2 on U2.CountryCode = C2.CountryCode
GROUP BY CountryName, Title
ORDER BY CountryName desc, AverageRatePerCountry desc, NumberOfRates desc, Title asc
I tried adding the below but clearly it does not work,
having AVG(CAST(Rate AS DECIMAL)) >=all and count(Rate) >= all
This is Homework, am not 100% sure if it is allowed to ask.
But, please i do not want the solution, just some pointers on what i am losing here.
Thank you in advance

Related

Which actor has the highest difference in ratings?

I need further help with my SQL problem.
In this database on movies, ratings and actors: https://i.stack.imgur.com/qFIbC.jpg
I am required to find the actor who has the largest difference between their best and their worst rated movie.
The condition is that the ratings cannot be lower than 3! (>3)
My current SQL looks as follows:
SELECT * FROM stars
JOIN ratings ON stars.movie_id = ratings.movie_id
WHERE ratings.movie_id = (
SELECT MAX(rating) - MIN(rating) FROM ratings
WHERE rating > 3);
My expectations were that I would get somewhat of a result in my Github terminal that I can work with to adjust my SQL query.
But I seem to have reached a dead-end and I'm not sure how to solve this solution
You need to GROUP BY actor to calculate everyone's rating range. Then, take the actor with the largest range. Something like this:
SELECT
person_id,
MAX(rating) - MIN(rating) AS rating_range
FROM
stars
JOIN ratings ON stars.movie_id = ratings.movie_id
WHERE
rating > 3
GROUP BY
person_id
ORDER BY
2 DESC
LIMIT
1
;

MS ACCESS / SQL: Select maximum count per person, per variable

In MS Access, I've joined two tables, one table is a list of sales and the city they took place (Sales), and another is a table of persons and the sales their participated in (SalePersons).
When joining the two tables, you can see that the combined table details many sales per person across many cities. My goal is obtain the most-frequented city for sales per each person.
For example, Customer 1 might have 2 sales in Baltimore, 1 sale in New York, and 3 Washington; customer 2 might have 3 sales in Washington, 4 sale in Wichita, and 1 sale in New York. The table needs to have only "Washington" listed for Customer 1, and only "Wichita" listed for Customer 2. If there's a tie, I'd like to list all the tied cities.
So far, I only have the initial join working.
SELECT SalePersons.PersonID, Count(Sales.SaleNum) AS CountOfSaleNum, Sales.CITY
FROM Sales INNER JOIN SalePersons ON Sales.SaleNum = SalePersons.SaleNum
GROUP BY SalePersons.PersonID, Sales.CITY;
But, as you might guess, this join will only give me the count of sales per city, per person across all cities. I need to retrieve only the 1 most-frequented city person.
I thought I could make this a subquery and wrap all this all under a Select MAX(CountOfSaleNum) clause, but that didn't work. I still have much to learn.
Thank you in advance! I don't know what I'd do without this site sometimes.
You can use window functions:
SELECT sp.*
FROM (SELECT sp.PersonID, COUNT(*) AS CountOfSaleNum, s.CITY,
ROW_NUMBER() OVER (PARTITION BY sp.PersonID ORDER BY COUNT(*) DESC) as seqnum
FROM Sales s INNER JOIN
SalePersons sp
ON s.SaleNum = sp.SaleNum
GROUP BY sp.PersonID, s.CITY
) sp
WHERE seqnum = 1;
In MS Access, you are stuck with a more complicated query:
SELECT sp.PersonID, COUNT(*) AS CountOfSaleNum, s.CITY
FROM Sales as s INNER JOIN
SalePersons as sp
ON s.SaleNum = sp.SaleNum
GROUP BY sp.PersonID, s.CITY
HAVING s.City = (SELECT TOP 1 s2.City
FROM Sales as s2 INNER JOIN
SalePersons as sp2
ON s2.SaleNum = sp2.SaleNum
WHERE sp2.PersonID = sp.PersonId
GROUP BY sp2.PersonId, s2.City
ORDER BY COUNT(*) DESC, s2.City
);

How do i get multiple values in sql?

I'm stuck in loop.
I have a postgres database and i have to filter the top-5, unique co-author pairs by number of jointly published papers.
I want to return pairs of author names and paper count
What i have so far:
select persons.name as person, count(papers.pkey) as amount
from persons
inner join authpapers on authpapers.akey = persons.akey
inner join papers on authpapers.pkey = papers.pkey
group by persons.name
order by amount desc limit 5;
As a result i get the first 5 authors ba name and paper count but i want papers where an author had a co author.
You can self-join the persons table to generate authors combinations, then bring each person's papers by joining authpapers once per user, and finally filter on matching papers. The final step is aggregation and sorting:
select p1.name as person1, p2.name person2, count(*) as amount
from persons p1
inner join persons p2 on p2.akey > p1.akey
inner join authpapers ap1 on ap1.akey = p1.akey
inner join authpapers ap2 on ap2.akey = p2.akey
where ap1.pkey = ap2.pkey
group by p1.akey, p2.akey
order by amount desc limit 5;
Note that you don't need the papers table to get the results that you want.

What makes this difference when using group by or join?

Can anybody tell the difference between them? The 1st and 3rd query can be successfully executed, and they have the same output. While the 2nd and 4th query cannot be executed, and they both raised an ERROR:
column "movie.title" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: SELECT title, (MAX(stars)-MIN(stars)) AS ratingspread.
My questions are:
why using m.mid are difference with r.mid while using group by (query 1 vs query 2)
why A inner join B is not equal to B inner join A (query 3 vs query 4)
SELECT title, (MAX(stars)-MIN(stars)) AS ratingspread
FROM rating r JOIN movie m
ON r.mid = m.mid
GROUP BY m.mid
ORDER BY ratingspread DESC, title;
SELECT title, (MAX(stars)-MIN(stars)) AS ratingspread
FROM rating r JOIN movie m
ON r.mid = m.mid
GROUP BY r.mid
ORDER BY ratingspread DESC, title;
SELECT title, (MAX(stars) - MIN(stars)) AS ratingspread
FROM movie
INNER JOIN rating USING(mId)
GROUP BY mId
ORDER BY rating_spread DESC, title;
SELECT title, (MAX(stars)-MIN(stars)) AS ratingspread
FROM rating
INNER JOIN movie USING(mId)
GROUP BY mId
ORDER BY ratingspread DESC, title
FYI the schema goes like this:
Movie ( mID, title, year, director )There is a movie with ID number mID, a title, a release year, and a director.
Reviewer ( rID, name ) The reviewer with ID number rID has a certain name.
Rating ( rID, mID, stars, ratingDate ) The reviewer rID gave the movie mID a number of stars rating (1-5) on a certain ratingDate.
Your queries are not producing what you think they are producing for a number of reasons.
Here is what you are really looking for I think:
SELECT
movie.mid
movie.title,
(MAX(rating.stars)-MIN(rating.stars)) AS ratingspread
FROM
movie
INNER JOIN rating on movie.mid = rating.mid
GROUP BY
movie.mid,
title
ORDER BY
(MAX(stars)-MIN(stars)) DESC,
title
There are a few things to point out: Firstly, you need to join on the matching column - in some of your queries you are joining mid to rid - these are unrelated fields. The movie ID is what joins the rating to the movie. Secondly, you are not getting the GROUP BY concept. What you are trying to do is get the spread of ratings for a given movie and display its title, so to display its title (and any other non-summarised data), you have to include the field in the group by. For further illustration, imagine you wanted to get the spread of all reviews by each reviewer, to see if they had any bias towards going hard or going soft on the movies they were reviewing. Here is how you would get the spread of reviews for each reviewer:
SELECT
reviewer.rid,
reviewer.name,
(MAX(rating.stars)-MIN(rating.stars)) AS ratingspread
FROM
reviewer
INNER JOIN rating on reviewer.rid = rating.rid
GROUP BY
reviewer.rid,
reviewer.name
ORDER BY
(MAX(stars)-MIN(stars)) DESC,
reviewer.name
By the way, the reason you want to include the ID as well as the title or reviewer name is to ensure you eliminate problems where two movies share the same title, or two reviewers have the same name.

SQL query for max(price) article per supplier. Can't understand the logic behind

This query select a list with the name and price of the most expensive articles by supplier, incluiding the provider name.
The tables are just:
Supplier: Code(PK) - Name
Articles: Code (PK) - Name - Price - Supplier (FK)
And the query is:
SELECT A.NAME, A.PRICE, S.NAME FROM ARTICLES A, SUPPLIERS S
WHERE A.SUPPLIER = S.CODE
AND A.PRICE =
(
SELECT MAX(A.PRICE)
FROM ARTICLES A
WHERE A.SUPPLIER = S.CODE
)
Would you please help me understand the logic behind? Why does this give me the max price PER SUPPLIER?
Thank you!
You inner query is getting the maximum price for a subset of articles - those that match the supplier.code passed in from the outer query. So the inner query says, "give me the highest price for supplier X."
The outer query is filtering the joined list to only provide those records that have match on the results from the inner query - those that happen to equal the highest price. It will match multiple records in the outer list if more than one record equates to the highest price for the supplier.