Suppose I have the following columns among three tables
Movie
mID | title | year | director
Reviewer
rID | name
Rating
rID | mID | stars | ratingDate
The instructions that I have been given are:
"For all cases where the same reviewer rated the same movie twice and gave it a higher rating the second time, return the reviewer's name and the title of the movie"
The way I have approached this so far is I have done a three way merge of all the tables to capture all the needed information. What I wanted to do next is create an new instance of this three way merge and find where reviewer and movie are equal and where rating is higher. This is what I have so far
SELECT *
FROM (SELECT *
FROM Movie Mov
INNER JOIN Rating Rat
ON Mov.mID = Rat.mID
INNER JOIN Reviewer REv
ON Rev.rID = Rat.rID) A, A table;
WHERE ...
The problem is that I am not able to create a new instance of A. Here I am attempting to do this here A table.
If anyone has any other suggestions on how to better approach this problem that is more clear please let me know.
So, with a problem like this the first task is to find the rows you want. I would do that with a query like this:
select *
from Rating as r1
where exists (
select 1
from rating as r2
where r1.rid = r2.rid
and r1.mid = r2.mid
and r1.stars < r2.stars
and r1.ratingDate < r2.ratingDate
)
Then add the parts you want to fetch (much as you were doing):
select title, name
from Rating as r1
inner join Movie as m on m.mid = r1.mid
inner join Reviewer as z on z.rid = r1.rid
where exists (
select 1
from rating as r2
where r1.rid = r2.rid
and r1.mid = r2.mid
and r1.stars < r2.stars
and r1.ratingDate < r2.ratingDate
)
Here is a fiddle with test data showing it working: http://sqlfiddle.com/#!7/5f0f8/3
Try this:
SELECT v.Name AS Reviewer, m.Name AS Movide
FROM (SELECT DISTINCT A.rID, A.mID
FROM Rating A INNER JOIN Rating B
ON A.rID = B.rID AND A.mID = B. mID
WHERE A.ratingDate > B.ratingDate
AND A.starts > B.starts
) s
JOIN Reviewer v ON v.rID =s.rID
JOIN Movie m ON m.mID = s.mID
I didn't test on Sqlite, however.
Related
The select function would sometumes output 1 result. Does anyone know why?
SELECT * FROM people
WHERE id = (SELECT person_id FROM stars
WHERE movie_id = (SELECT id FROM movies
WHERE year = 2004))
ORDER BY birth;
You should avoid subqueries. You're best bet is to use something like the following code:
SELECT
ppl.* -- to get just people information
FROM
people ppl,
stars sta,
movies mov
WHERE
ppl.id = sta.person_id
AND sta.movie_id = mov.id
AND mov.YEAR = 2004
ORDER BY
ppl.birth;
If you want to have stars information or movie information you just need to add the desired fields on the return like mov.title (assuming you have a column named title on movies table :P)
EDIT:
As pointed out, I will leave an example using JOIN also.
SELECT
ppl.* -- to get just people information
FROM
people AS ppl
INNER JOIN
stars AS sta ON ppl.id = sta.person_id
INNER JOIN
movies AS mov ON sta.movie_id = mov.id
WHERE
mov.YEAR = 2004;
I have a movie table which has year and movie details like title , movie id( mid) and a table m_cast where i have all the actors in that movie.
I would like to get all the actors who have never been unemployed for more than 3 years. ( Assuming actors are unemployed between two consecutive movies)
i code i came up with is
select a.yr1 y1 , b.yr2 y2 , a.yr1 - b.yr2 diff from
(select substr(substr(trim(year),-5),0,5) yr1 , * from movie m inner join m_cast p on m.mid = p.mid order by pid , yr1) a ,
(select substr(substr(trim(year),-5),0,5) yr2 , * from movie m inner join m_cast p on m.mid = p.mid order by pid, yr2) b on a.yr1 > b.yr2
where not exists
(select count(*) from movie m inner join m_cast p on m.mid = p.mid
and cast(substr(substr(trim(year),-5),0,5) as integer) < a.yr1 and cast(substr(substr(trim(year),-5),0,5) as integer) > b.yr2)
Self join itself takes a lot of time. And lag and lead functions do not work in SQLite version i am using.
I'm assuming the movie table has a column called year, and a column to identify the actor's name. Something like : year int, actorId int
The fastest way to run your query is to filter the last 3 years from your movie table and then to group by your actors the distinct count of years.
Example after filtering
ActorId Year
1. 2018
1. 2018
1. 2017
2. 2016
2. 2017
2. 2018
Then group by and select distinct :
Select actorId from movieTable group by actorId having count (distinct (Year)) =3
And that will only return the actors who have worked in the last 3 years. Once you have your actors id's filtered out in that column do a join to the table that holds their names.
Sorry about the format of my writing - did it from my cellphone.
Regards,
Jorge D. Lopez
My school task was to get names from my movie database actors which play in movies with highest ratings
I made it this way and it works :
select name,surname
from actor
where ACTORID in(
select actorid
from actor_movie
where MOVIEID in (
select movieid
from movie
where RATINGID in (
select ratingid
from rating
where PERCENT_CSFD = (
select max(percent_csfd)
from rating
)
)
)
);
the output is :
Gary Oldman
Sigourney Weaver
...but I'd like to also add to this select mentioned movie and its rating. It accessible in inner selects but I don't know how to join it with outer select in which i can work just with rows found in Actor Table.
Thank you for your answers.
You just need to join the tables properly. Afterwards you can simply add the columns you´d like to select. The final select could be looking like this.
select ac.name, ac.surname, -- go on selecting from the different tables
from actor ac
inner join actor_movie amo
on amo.actorid = ac.actorid
inner join movie mo
on amo.movieid = mo.movieid
inner join rating ra
on ra.ratingid = mo.ratingid
where ra.PERCENT_CSFD =
(select max(percent_csfd)
from rating)
A way to get your result with a slightly different method could be something like:
select *
from
(
select name, surname, percent_csfd, row_number() over ( order by percent_csfd desc) as rank
from actor
inner join actor_movie
using (actorId)
inner join movie
using (movieId)
inner join rating
using(ratingId)
(
where rank = 1
This uses row_number to evaluate the "rank" of the movie(s) and then filter for the movie(s) with the highest rating.
I have three tables:
CREATE TABLE Movie
(
movieId INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
title VARCHAR(255) NOT NULL,
moviePath VARCHAR(500) NOT NULL
);
CREATE TABLE Rating
(
rid INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
mid INTEGER FOREIGN KEY REFERENCES Movie(movieId) ON DELETE CASCADE,
uid INTEGER FOREIGN KEY REFERENCES User(id) ON DELETE CASCADE,
rating INTEGER NOT NULL,
);
CREATE TABLE Genre(
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
movieId INTEGER NOT NULL FOREIGN KEY REFERENCES Movie(movieId) ON DELETE CASCADE,
genre VARCHAR(255) NOT NULL
);
I want to create an sql query which gives me the most seen movie(with moviepath, title) from the the most seen genre back.
Any ideas?
UPDATE
Results:
| MID | TITLE | MOVIEPATH |
--------------------------------
| 4 | Happy days | a |
| 4 | Happy days | a |
It's really great if you had provided some sample data to match.. Well try this out. Looking at your earlier question this answer is drafted.
SQLFIDDLE DEMO
select t.mid, t.sum_rating,
m.title, m.moviepath, g.genres
from (
select mid,
sum(rating) as sum_rating,
dense_rank() over (order by
sum(rating) desc) as rnk
from rating
group by mid
) t
left join movie m
on m.movieid = t.mid
left join genre g
on g.movieid = m.movieid
where t.rnk = 1;
Results:
| MID | SUM_RATING | TITLE | MOVIEPATH | GENRES |
------------------------------------------------------
| 4 | 37 | Happy days | a | comedy |
| 4 | 37 | Happy days | a | RomCom |
You may use this alternative as HSQL doesn't support dense_rank:
SQLFIDDLE DEMO ALTERNATIVE
Query with : order by desc and top 1
-- alternatively
select t.mid, t.sum_rating,
m.title, m.moviepath, g.genres
from (
select top 1 mid,
sum(rating) as sum_rating
from rating
group by mid
order by sum_rating desc
) t
left join movie m
on m.movieid = t.mid
left join genre g
on g.movieid = m.movieid
;
You could calculate the rating by summing all ratings for a movie in a subquery. Another subquery could calculate the highest rating per genre. By joining them together, you'd filter only the top movies per genre:
select *
from Movie m
join Genre g
on g.movieId = m.movieId
join (
select r.mid
, sum(Rating) as SumRating
from Rating r
group by
r.mid
) r
on r.mid = m.movieId
join (
select g.id as gid
, max(SumRating) as MaxGenreRating
from (
select r.mid
, sum(Rating) as SumRating
from Rating r
group by
r.mid
) r
join Genre g
on g.movieId = r.mid
group by
g.id
) filter
on filter.gid = g.id
and filter.MaxGenreRating = r.SumRating
Where can we found the count of views? With this tables you can find the highest rated movie by using a query like this:
select Movie.movieId, Movie.title, Movie.moviepath
from movie, rating, genre
where
movie.id = rating.mid and
movie.id = genre.movieId
order by rating desc
limit 1; // limit is used if you are using MySQL. In other databases you can use suitable sql query.
But if you are looking for the most seen movie from most seen genre, you have to have the view count of each movie and each genre inside your tables.
I can recommend you using aggregate max on the rating together with group by on genre
select max(Rating.rating) as max_rating, Genre.genre, Movie.movieId from Movie
inner join Rating on Movie.movieId = Rating.mid
inner join Genre on Movie.movieId = Genre.movieId
group by Genre.genre;
I am not so sure that this will work 100% since I didn't try it, but I the idea is to use group by. It it ment to be used with aggregates like count, max, min, avg and so on.
I hope that helps
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 reviewers that have a NULL value for the date (ratingDate) meaning I need to extract information from both the Reviewer and Rating table.
I have tried different things with the IS NULL command but to no avail. Any help would be appreciated.
SELECT
rev.rID
, rev.name
, rat.mID
, rat.stars
FROM
Reviewer AS rev
JOIN
Rating AS rat
ON rat.rID = rev.rID
WHERE
rat.ratingDate IS NULL
SELECT Reviewer.name
FROM Reviewer
INNER JOIN Rating
ON Reviewer.rID = Rating.rID
WHERE Rating.ratingDate IS NULL
Try this, I think it will do.
it should be trivial
select *
from rating
join reviewer on rating.rid = reviewer.rid
join movie on rating.mid = movie.mid
where ratingdate is null
so there might be other problems - e.g. the ratingdate is not a date and not null but an empty string (ratingdate = '')?
You need to use a LEFT JOIN. That is, a JOIN that includes null values on one side.