cs50 - pset7 - movies - 10.sql failed check50 test - sql

I'm currently working on 10.sql which asked me to find all people who directed a movie that received a rating of at least 9.0
Here's the schema:
CREATE TABLE movies (
id INTEGER,
title TEXT NOT NULL,
year NUMERIC,
PRIMARY KEY(id)
);
CREATE TABLE stars (
movie_id INTEGER NOT NULL,
person_id INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id),
FOREIGN KEY(person_id) REFERENCES people(id)
);
CREATE TABLE directors (
movie_id INTEGER NOT NULL,
person_id INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id),
FOREIGN KEY(person_id) REFERENCES people(id)
);
CREATE TABLE ratings (
movie_id INTEGER NOT NULL,
rating REAL NOT NULL,
votes INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id)
);
CREATE TABLE people (
id INTEGER,
name TEXT NOT NULL,
birth NUMERIC,
PRIMARY KEY(id)
);
Here's the code I wrote:
SELECT DISTINCT name FROM people
JOIN directors ON directors.person_id = people.id
JOIN movies ON movies.id = directors.person_id
JOIN ratings ON ratings.movie_id = movies.id
WHERE ratings.rating >= 9.0;
When I worked on sqlite3, it returned me a list of names. But it failed the check50 test with error message of 'Query did not return results'. I couldn't figure out why. Can anyone tell me what I did wrong? Many thanks

Why do you need to join on movies? Try:
SELECT
name
FROM
people
JOIN directors ON people.id = directors.person_id
JOIN ratings ON directors.movie_id = ratings.movie_id
WHERE
ratings.rating >= 9.0

Related

Find the count of posts, upvotes and downvotes on the posts of Users with Badge” Tech Champion”

I am working on an assignment and got stuck on this query. I am not able to create this query Find the count of posts, upvotes and downvotes on the posts of Users with Badge” Tech Champion” so I have created a separate table for upvotes and downvotes and Stored some predefined badge and create userbadge table to defined badges for users.
Here are my some of my tables.
CREATE TABLE users (
Id serial PRIMARY KEY,
username VARCHAR(80) NOT NULL,
created_on DATE NOT NULL DEFAULT CURRENT_DATE,
email TEXT,
Age INTEGER
);
CREATE TABLE POSTS (
Id serial PRIMARY KEY,
Created_on date NOT NULL DEFAULT CURRENT_DATE,
title VARCHAR(60) NOT NULL,
description TEXT NOT NULL,
user_id INTEGER REFERENCES users(id)
);
CREATE Table UpVotes
(
Id serial PRIMARY KEY NOT NULL,
Created_on date NOT NULL DEFAULT CURRENT_DATE,
post_id INTEGER REFERENCES Posts(id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE
);
CREATE Table DownVotes
(
Id serial PRIMARY KEY NOT NULL,
Created_on date NOT NULL DEFAULT CURRENT_DATE,
post_id INTEGER REFERENCES Posts(id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE Badge(
Id serial PRIMARY KEY NOT NULL,
BadgeName TEXT Not NULL
);
CREATE Table UserBadge (
Id serial PRIMARY KEY NOT NULL,
user_id INTEGER REFERENCES Users(id) ON DELETE CASCADE,
badge_id INTEGER REFERENCES Badge(id) ON DELETE CASCADE
);
I have come up with this solution but it is not correct.
SELECT us.id ,us.username, ub.Badge_id, COUNT(Po.title) As post_count, Count(Uv.post_id) FROM Users As us
JOIN UserBadge As ub On ub.user_id = us.id
JOIN Posts As Po On Po.user_id = us.id
JOIN UpVotes As Uv On Po.id= Uv.post_id
WHERE ub.badge_id=4
GROUP BY us.id, us.username, ub.Badge_id;

How to find records with same values within a subquery that i need to order

I need to write a SQL query to list all movies released in 2010 and their ratings, in descending order by rating. For movies with the same rating i need to order them alphabetically by title. I`m stuck at the part with the movies with the same rating. Thanks !
CREATE TABLE movies (
id INTEGER,
title TEXT NOT NULL,
year NUMERIC,
PRIMARY KEY(id)
);
CREATE TABLE stars (
movie_id INTEGER NOT NULL,
person_id INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id),
FOREIGN KEY(person_id) REFERENCES people(id)
);
CREATE TABLE directors (
movie_id INTEGER NOT NULL,
person_id INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id),
FOREIGN KEY(person_id) REFERENCES people(id)
);
CREATE TABLE ratings (
movie_id INTEGER NOT NULL,
rating REAL NOT NULL,
votes INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id)
);
CREATE TABLE people (
id INTEGER,
name TEXT NOT NULL,
birth NUMERIC,
PRIMARY KEY(id)
);

Using UDF for value of a column postgresql

Let's say I already have 2 table with movies and their ratings.
CREATE TABLE public.movies (
movieid int4 NOT NULL,
averagerating float4 NULL,
title varchar(255) NOT NULL,
"year" int4 NULL,
CONSTRAINT movies_pkey PRIMARY KEY (movieid)
);
CREATE TABLE public.ratings (
movie_id int4 NOT NULL,
user_id int4 NOT NULL,
rating float4 NOT NULL,
timestmp varchar(255) NOT NULL,
CONSTRAINT ratings_pkey PRIMARY KEY (movie_id, user_id),
CONSTRAINT fk44trpo3u915t27ybt03ib4h0o FOREIGN KEY (movie_id) REFERENCES movies(movieid),
CONSTRAINT fk7ymub8kd95i2xlklgole3i684 FOREIGN KEY (user_id) REFERENCES usrs(userid)
);
For now column averagerating in movies is empty everywhere. I want to attach my UDF average_movie_rating to this column
Something like update movies set averagerating = average_movie_rating(movies.movieid)
This function:
create or replace function average_movie_rating(movieid integer)
returns float8 as $averagerating$
declare
averagerating float8;
begin
select avg(r.rating) into averagerating from ratings r where r.movie_id = $1;
return averagerating;
end
$averagerating$ language plpgsql;
Would it be possible and if yes, how do I pass this movieid to the function?
Unless required for performance reasons, you should calculate that value when you select from the database. If you have to persist it, use a trigger on ratings that modifies movies.

How to consolidate my data for SQL Join Clause

I have to write a query with the following criteria:
Write a query to list the title and artist of ONLY the items that have been ordered. Only list each title once.
Here are the CREATE tables that were made that cannot be changed.
CREATE TABLE artists
(
artist_id INT NOT NULL,
artist_name VARCHAR(30),
CONSTRAINT artist_pk PRIMARY KEY (artist_id)
);
CREATE TABLE items
(
item_id INT NOT NULL,
title VARCHAR(50) NOT NULL,
artist_id INT NOT NULL,
unit_price DECIMAL(9,2) NOT NULL,
CONSTRAINT items_pk PRIMARY KEY (item_id),
CONSTRAINT items_fk_artists
FOREIGN KEY (artist_id) REFERENCES artists (artist_id)
);
CREATE TABLE orders
(
order_id INT NOT NULL,
customer_id INT NOT NULL,
order_date DATE NOT NULL,
shipped_date DATE,
employee_id INT,
CONSTRAINT orders_pk PRIMARY KEY (order_id),
CONSTRAINT orders_fk_customers
FOREIGN KEY (customer_id) REFERENCES customers (customer_id),
CONSTRAINT orders_fk_employees
FOREIGN KEY (employee_id) REFERENCES employees (employee_id)
);
Here is what I have done for my script.
SELECT
items.title, artists.artist_name, orders.order_date
FROM
items
JOIN
orders
JOIN
artists;
Please let me know how I can consolidate.
You should say the structures of tables with respect to keys between tables.

Need help with some Oracle SQL Queries

Here is the question posed by a professor: Find the minimum and maximum length of movies playing in each city.
And here is how I have my tables structured:
CREATE TABLE Theatres (
Name varchar2(50) not null,
City varchar2(50) not null,
State varchar2(50) not null,
Zip number not null,
Phone varchar2(50) not null,
PRIMARY KEY (Name)
);
CREATE TABLE Movies (
Title varchar2(100) not null,
Rating NUMBER not null,
Length NUMBER not null,
ReleaseDate date not null,
PRIMARY KEY (Title),
CHECK (Rating BETWEEN 0 AND 10),
CHECK (Length > 0),
CHECK (ReleaseDate > to_date('1/January/1900', 'DD/MONTH/YYYY'))
);
CREATE TABLE ShownAt (
TheatreName varchar2(50) not null,
MovieTitle varchar2(100) not null,
PRIMARY KEY (TheatreName, MovieTitle),
FOREIGN KEY (TheatreName) REFERENCES Theatres(Name),
FOREIGN KEY (MovieTitle) REFERENCES Movies(Title)
);
I've tried a few different queries, but keep getting issues. Here is what I have:
SELECT MIN(Movies.Length), MAX(Movies.Length), Theatres.Name
FROM Theatres, Movies, ShownAt
WHERE ShownAt.TheatreName = Theatres.Name AND
ShownAt.MovieTitle = Movies.Title AND
Theatres.City IN (SELECT UNIQUE City FROM Theatres);
Anybody see anything wrong? Thanks for the help!
You were pretty close I think. Just missing GROUP BY
SELECT
MIN(Movies.Length) AS Shortest,
MAX(Movies.Length) AS Longest,
Theatres.City
FROM Theatres
JOIN ShownAt ON ShownAt.TheatreName = Theatres.Name
JOIN Movies ON ShownAt.MovieTitle = Movies.Title
GROUP BY Theatres.City
I believe this would do the trick:
SELECT T.City, MIN(M.Length) AS MinLength, MAX(M.Length) AS MaxLength
FROM Movies AS M
JOIN ShownAt AS S ON S.MovieTitle = M.Title
JOIN Theatres AS T ON S.TheatreName = T.Name
GROUP BY T.City