How do I do this SQL query - sql

The following are the tables I am working with:
Movie(mID, title, year, director)
Reviewer(rID, name)
Rating(rID, mID, stars, ratingDate)
which statement would I use to display all movies that have no ratings. I am new to the SQL language and can't quite see how this can be done. From what I have been told this is a relatively simple query.

SELECT * FROM Movie WHERE Movie.mid NOT IN (SELECT mID FROM Rating)

There are three ways to do this. My preference is for an Anti-Join, which is a LEFT JOIN with a where clause test for IS NULL on the right side of the join.
SELECT *
FROM
Movie
LEFT JOIN Rating
ON moive.Mid = rating.mid
WHERE
rating.mid is null

select * from movie where mID not in (select mId from rating)

You can use the NOT EXISTS clause. A good example for Oracle is at http://www.dba-oracle.com/sql/t_subquery_not_in_exists.htm. The syntax may vary depending on your database

Related

How can I generate SQL query with average score for movie from different tables?

I would very much appreciate your help with this query. My database (Oracle) has a table called MOVIES with fields like id and title. Then there is another one, SCORES which has fields like movie_id and score. It is a one-to-many relation.
Now, I'm looking for a way to get a SELECT that will give me a result like one below:
movie-title, avg(score where movie.id=scores.movie_id)
It looks simple at first glance, but I cannot pass through it. Any suggestions?
First off, you need to join the tables on the pk/fk
Then, in order to get the avg for each movie, you need to use group and specify the column (score) that you want.
In this case we are grouping by the id because it's unique and the movie title since it is in the select clause
select m.title, avg(s.score)
from movie m
inner join scores s
on m.id = s.movie_id
group by m.id, m.title
You just need join and group by as follows:
Select m.title, avg(s.score)
From movies m join scores s
On m.id = s.movie_id
Group by m.id, m.title

SQL Collect duplicates to one place? PostgreSQL

Sorry I'm new here and I'm also new with SQL and can't really explain my problem in the title...
So I have a TV show database, and there I have a Genre column, but for a TV show there are multiple Genres stored, so when I'm selecting all my TV Shows how can I combine them?
It needs to look like this:
https://i.stack.imgur.com/3EhBj.png
So I have to combine the string together, here is my code so far what I wrote:
SELECT title,
year,
runtime,
MIN(name) as name,
ROUND(rating, 1) as rating,
trailer,
homepage
FROM shows
JOIN show_genres
on shows.id = show_genres.show_id
JOIN genres
on show_genres.genre_id = genres.id
GROUP BY title,
year,
runtime,
rating,
trailer,
homepage
ORDER BY rating DESC
LIMIT 15;
I also have some other stuff here, that's my exerciese tasks! Thanks!
Also here is the relationship model:
https://i.stack.imgur.com/M89ho.png
Basically you need string aggregation - in Postgres, you can use string_agg() for this.
For efficiency, I would recommend moving the aggregation to a correlated subquery or a lateral join rather than aggregating in the outer query, so:
SELECT
s.title,
s.year,
s.runtime,
g.genre_names,
ROUND(s.rating, 1) as rating,
s.trailer,
s.homepage
FROM shows s
LEFT JOIN LATERAL (
SELECT string_agg(g.name, ', ') genre_names
FROM show_genres sg
INNER JOIN genres g ON g.id = sg.genre_id
WHERE sg.show_id = s.id
) g ON 1 = 1
ORDER BY s.rating DESC
LIMIT 15

How can I rewrite a SQL query without any sub-queries?

How can I rewrite this query without using any subqueries in SQL?
I'm not too familiar with how to do this, but I think it's done by using "join."
SELECT title
FROM Movies Old
Where year < ANY
(SELECT year
FROM Movies
WHERE title = Old. title
);
(Note: this comes from the relation Movies(title, year, length, genre, studioName, producerC#))
To literally rewrite your current query using joins you can try this:
SELECT m1.title
FROM Movies m1
INNER JOIN Movies m2
ON m1.title = m2.title AND
m1.year < m2.year
But if all you really want is to find movie titles which appear more than once, then when not just use a GROUP BY query:
SELECT title
FROM Movies
GROUP BY title
HAVING COUNT(*) > 1

SQL - HAVING with recursive statement

I am not sure the title corresponds to my problem but this is the best way I could describe it.
I was wondering if it was possible theoretically to have a query with a recursive statement in the having clause. For instance:
SELECT a_name
FROM (
SELECT Author.id as a_id, Author.name as a_name, COUNT ( * ) as science_fiction_per_author
FROM Title, Author, Title_tags, Tags, Publication_authors, Publication, Publication_content
WHERE ...
GROUP BY a_id
HAVING science_fiction_per_author = MAX(science_fiction_per_author)
);
It's not really recursion but you can use the same phrase twice to find the individual with the highest count. This is based on the movie database at http://sqlzoo.net/wiki/More_JOIN_operations
The phrase
SELECT actor.name,count(movieid) moviesPerActor
FROM actor join casting ON actor.id=actorid
GROUP BY actor.name
Lists each actor name and the number of movies made.
The same phrase is used twice. The A version is used to find the highest number of movies made by a single actor, the B version is used to identify that actor.
SELECT B.name from
(SELECT MAX(moviesPerActor) as highestNumberOfMovies
FROM(
SELECT actor.name,count(movieid) moviesPerActor
FROM actor join casting ON actor.id=actorid
GROUP BY actor.name
) as A) as A1
JOIN
(
SELECT actor.name,count(movieid) moviesPerActor
FROM actor join casting ON actor.id=actorid
GROUP BY actor.name
) as B
ON B.moviesPerActor = highestNumberOfMovies
In some versions of SQL (including MSSQL and Oracle) you can use windowing functions to identify the element with the highest value more efficiently.

SQL inner join with count() condition, and relationnal algebra

I have these tables:
Movies (id, name)
Cast (idmovie, actor)
And I would like to count the number of actors for each movie and then only get movies with more than 10 actors. I have a query to count the number of actors for each movie, which goes like this:
SELECT idmovie, count(actor) FROM Cast GROUP BY idmovie HAVING count(actor) > 10;
Now, I wonder how to get that result and join it to the Movies table.
I tried:
SELECT name FROM Movies INNER JOIN (SELECT idmovie FROM Cast GROUP BY idmovie HAVING count(actor) >2) Cast ON Cast.idmovie = Movies.id;
But it doesn't work.
I also have to translate it to relational algebra.
π name (σ (count(σ id = idmovie))) Movies⨝Cast
Which is obviously wrong...
Any help?
Try this...
SELECT m.name, COUNT(c.actor) AS 'ActorsCount'
FROM Movies m INNER JOIN [Cast] c ON m.id = c.idmovie
GROUP BY m.name HAVING COUNT(c.actor) > 10;
The query looks correct to me except perhaps that you aliased the nested query with Cast which is also the name of a table. I'm not sure what effect that'd have but I'd expect it to confuse MySQL. Try the following:
SELECT name FROM Movies INNER JOIN
(SELECT idmovie FROM Cast GROUP BY idmovie HAVING count(actor) >2) CastCount
ON CastCount.idmovie = Movies.id;
I didn't try it, but I think that'll work