New to SQL here. I tried WITH clause today and can't figure out why I get an error from my query.
Table structure
CREATE TABLE actor
(
actor_id
first_name
last_name
last_update
)
CREATE TABLE film_actor
(
actor_id
film_id
last_update
)
CREATE TABLE film
(
film_id
title
release_year
rating
)
Query that causes the error:
WITH tempotable(actorwithid) AS
(
SELECT
actor.actor_id, first_name, last_name,film_id
FROM
actor
LEFT OUTER JOIN
film_actor ON actor.actor_id = film_actor.actor_id
WHERE
first_name = 'Nick'
AND last_name = 'Wahlberg'
)
SELECT
title, film.film_id, first_name, last_name, actor_id
FROM
film
LEFT OUTER JOIN
tempotable ON film.film_id = tempotable.film_id
ORDER BY
film_id
I can get desired outcome if I switch second left outer join table but I also want actor_id column in my final outcome. After add extra SELECT actor_id in second join, an error: column "actor_id" does not exist pop up. But actor_id column suppose the first column in the tempotable.
I tried tempotable.actor_id still same error.
This is a question from Udemy online sql lessons. Very appreciate for any help!
Related
I am new at SQL and I am trying to select a max value from a view. The database is of movies and actors, and the nested query part works. I am trying to find the actor that has the most co-actors, so the first thing I did was calculate the number of co-actors for each actor. Now I would like to select the value with the highest co-actors and return the number and the name of the actor. Please find below the attempted code:
CREATE VIEW actorview AS
SELECT COUNT(DISTINCT A2.name) AS Count, A.name AS Name
FROM actors A, actors A2
WHERE A2.mid =A.mid
GROUP BY A.name;
SELECT Name, MAX(Count) FROM actorview;
actors table
CREATE TABLE actors (mid integer NOT NULL, name varchar, cast_position integer, PRIMARY KEY (mid, name),
FOREIGN KEY (mid) REFERENCES movies(mid) ON DELETE CASCADE ON UPDATE CASCADE);
Edit:
In the above table mid (movie ID) represents the Movies an actor has been in, any actor that shares the same mid as another was in a movie with that actor. The view works for finding the number of co-actors every actor has, now I just need to select from that list the actor that has the most co-actors.
You can use analytical function rank as follows:
Select * from
(Select a.name, count(distinct a2.name) as co_actors,
Rank() over (order by count(distinct a2.name) desc ) as rn
From actors a join actors c
On a.mid = a2.mid and a.name <> a2.name
Group by a.name) t
Where rn = 1
I have three tables: films, actors and the relationship actors_film.
I'm trying to decide which actors has been in the most number of movies. If the actor has been in a movie this is shown with actor_id(primary key).
I figured I want to count the number of times each actor_id shows in the table film_actor for each film_id, and then connect this with the right name(actor.first_name).
I've got the first part down, but can't seem to connect the Count-value to the right name.
SELECT actor_id, COUNT(*) AS number_of_films
FROM film_actor
GROUP by actor_id
ORDER by 2
DESC limit 1;
How would I go forward connecting the actors name from the actor-table?
I'm thinking I need some form of:
WHERE actor.actor_id = film_actor.actor_id.
You need a simple inner join between the table actors and the table actors_film:
SELECT a.actor_name, a.actor_id, COUNT(*)
FROM actors a INNER JOIN actors_films af
ON a.actor_id = af.actor_id
GROUP BY a.actor_name, a.actor_id
ORDER BY 3;
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 a table like this
ID|list
1|:A:B:C:
2|:B:D:A:
3|:C:A:D:
I want to count the number of each of A,B,C,D and group them as
A|3
B|2
C|2
D|2
I was thinking about iterating through the table and inserting values in to a temporary table from count statements like the following
select count(*) from table where list like %:A:%
It does look ugly.Is there a better way to do this?
(I am using sqlite from qt)
Never, never, never store multiple values in one column! A better DB design would be
movies table
----------
id
name
release_date
...
actors table
------------
id
first_name
last_name
birth_date
...
movie_cast table
----------------
movie_id
actor_id
You could then select all actors of a specific movie like this
select a.lastName, a.first_name
from actors a
join movie_cast c on c.actor_id = a.id
join movies m on c.movie_id = m.id
where m.name = 'Citizen Kane'
Or select all movies a specific actor stars in like this
select m.name
from actors a
join movie_cast c on c.actor_id = a.id
join movies m on c.movie_id = m.id
where a.lastName ='Wayne'
and a.first_name 'John'
Suppose you had two tables. One called MOVIES:
MovieId
MovieName
Then another called ACTORS that contains people who appear in those movies:
MovieId
ActorName
Now, I want to write a query that returns any movie that contains ONE OR MORE of the following actors: "Tom Hanks", "Russell Crowe" or "Arnold Schwarzenegger".
One way to do it would be something like:
SELECT DISTINCT A.MovieId, M.MovieName FROM ACTORS A
INNER JOIN MOVIES M USING (MovieId)
WHERE A.ActorName IN ('Tom Hanks', 'Russell Crowe', 'Arnold Schwarzenegger');
Which is perfectly fine, however in my case I might have several more of these conditions on the WHERE clause so I want to find a way to make the MOVIES table the primary table I select from.
What's the best way to query for this? I'm using Oracle 11g if that matters, but I'm hoping for a standard SQL method.
You can use EXISTS or IN subqueries:
SELECT *
FROM MOVIES m
WHERE EXISTS
(
SELECT *
FROM ACTORS a
WHERE a.MovieId = m.MovieId
AND a.ActorName IN ('Tom Hanks', 'Russell Crowe', 'Arnold Schwarzenegger')
)
or
SELECT *
FROM MOVIES m
WHERE m.MovieId IN
(
SELECT a.MovieId
FROM ACTORS a
WHERE a.ActorName IN ('Tom Hanks', 'Russell Crowe', 'Arnold Schwarzenegger')
)
First you should have a 3rd table implementing the n:m relationship:
CREATE TABLE movie (
movie_id int primary key
,moviename text
-- more fields
);
CREATE TABLE actor (
actor_id int primary key
,actorname text
-- more fields
);
CREATE TABLE movieactor (
movie_id int references movie(movie_id)
,actor_id int references actor(actor_id)
,CONSTRAINT movieactor_pkey PRIMARY KEY (movie_id, actor_id)
);
Then you select like this:
SELECT DISTINCT m.movie_id, m.moviename
FROM movie m
JOIN movieactor ma USING (movie_id)
JOIN actor a USING (actor_id)
WHERE a.actorname IN ('Tom Hanks', 'Russell Crowe', 'Arnold Schwarzenegger');
Note, that text literals are enclose in single quotes!