With this query I display the year field, the first record in ASC order, and the last in DESC order.
Works well if the year field is different
example:
1960-1970
but if the field is the same
example:
1960
I see duplicate
1960 - 1960
I would only like to see once
1960
how to do?
$query = "(SELECT
year as year_asc
FROM film_actor
INNER JOIN film ON film_actor.film_id = film.film_id
INNER JOIN actor ON film_actor.actor_id = actor.actor_id
WHERE film_actor.actor_id = $actor_id
ORDER BY year ASC
LIMIT 1)
UNION ALL
(SELECT
year as year_desc
FROM film_actor
INNER JOIN film ON film_actor.film_id = film.film_id
INNER JOIN actor ON film_actor.actor_id = actor.actor_id
WHERE film_actor.actor_id = $actor_id
ORDER BY year DESC
LIMIT 1)";
you may use UNION, rather than UNION ALLsince UNION will eliminate duplicates.
If you want the minimum and maximum years, you can put them in a single query:
SELECT MIN(year) as min_year, MAX(year) as max_year
FROM film_actor fa JOIN
film f
ON fa.film_id = f.film_id JOIN
actor a
ON fa.actor_id = a.actor_id
WHERE fa.actor_id = $actor_id;
If you want a single column, perhaps with a hyphen, you can use:
SELECT CONCAT_WS('-', MIN(YEAR), NULLIF(MAX(YEAR), MIN(YEAR)))
Related
"Determine if there are actors with the same first name who appeared in the same movie."
This is my task and I'm supposed to do that with subqueries and I just dont really know what else to do. I tried everything with group by, order by and having count but I just don't get to the point where I get the same first name actors with the same movie.
Maybe someone can help me? I am using Sakila Database
SELECT
a.first_name
,(a.last_name)
,a.actor_id
, f.title
FROM actor a
JOIN film_actor fa ON fa.actor_id = a.actor_id
JOIN film f ON f.film_id = fa.film_id
JOIN(SELECT b.first_name, COUNT(*)
FROM actor B
GROUP BY b.first_name
HAVING COUNT(*) > 1 ) b
ON a.first_name = b.first_name
GROUP BY a.last_name
HAVING COUNT(f.title) > 1
ORDER BY a.first_name
You can do this with joins only:
select f.title, a1.first_name, a1.last_name as last_name_1, a2.last_name as last_name_2
from film f
inner join film_actor fa1 on fa1.film_id = f.film_id
inner join film_actor fa2 on fa2.film_id = f.film_id
inner join actor a1 on a1.actor_id = fa.actor_id
inner join actor a2 on a2.actor_id = fa.actor_id
where a1.first_name = a2.first_name and a1.actor_id < a2.actor_id
Starting from the film table, this follows the relationships to actor through film_actor twice, and then filters on diffrerent actors that have the same first name.
As a result, you get tuples of actors that have the same last name and played in the same film. The inequality condition ensures that there are no "mirror" records (that is, each tuple appears only once per film).
I would simply use aggregation:
SELECT fa.film_id, a.first_name,
GROUP_CONCAT(a.last_name) as last_names,
GROUP_CONCAT(a.actor_id) as actor_ids
FROM actor a JOIN
film_actor fa
ON fa.actor_id = a.actor_id
GROUP BY fa.film_id, a.first_name
HAVING COUNT(*) > 1;
Your question doesn't specify what the result set should look like. This returns one row per actors with the same first name in a film. The last names are concatenated into a string as are the actor ids.
How about this:
SELECT f.title, f.film_id, a.first_name, a.last_name, a.actor_id
FROM actor a
JOIN film_actor fa ON fa.actor_id = a.actor_id
JOIN film f ON f.film_id = fa.film_id
WHERE a.first_name IN (
SELECT a2.first_name
FROM actor a2
JOIN film_actor fa2 ON fa2.actor_id = a2.actor_id
JOIN film f2 ON f2.film_id = fa2.film_id
WHERE a2.actor_id <> a.actor_id AND f2.film_id = f.film_id
)
ORDER BY f.title ASC, a.last_name ASC, a.first_name ASC
Explaining query step-by-step
SELECT the needed fields from the joined tables
JOIN the necessary tables
WHERE (here is the subquery) a.first_name is in the set of:
firstnames of actors, different than the current actor (a2.actor_id <> a.actor_id) and the film is the same (f2.film_id = f.film_id)
The subquery in where is a similar select with joins query as the parent query.
PS:
One can do variations on this basic query template:
Eg film_id can be given as parameter, so one can find all actors with same name for specific film.
Also one can group and count how many actors appeared in same film wih same name eg by grouping on film_id and counting.
One can even optimise a bit the query by removing unnecessary joins (eg film.title may not be needed at all) and so on..
The advantage of having single results returned (instead of tuples or aggregates) is that number of actors with same name in same film is not fixed and manipulating the results, eg by grouping and counting or getting further info for each actor, is easier.
The price is a slightly more complex and potentialy slower query.
I have a question, I am trying to list all of the actors for each movie in my database. Right now I have this SQL
SELECT title, count(1) COUNT, actor.first_name, actor.last_name
FROM film
INNER JOIN film_actor ON film.film_id = film.actor.film_id
INNER JOIN actor ON film_actor.actor_id = actor.actor_id
GROUP BY title.
What I am trying to do is format my out put into a text file like this:
Title:Number of Actors in each film: Actor first name(1): Actor last name(2) : Actor first name(2): Actor last name(2) ... ect
But for example, in the first film there are ten actots for this film. How would I print out the first and last name of each actor for each movie.
The problem is you want aggregate and non-aggregate data.
One way to achieve this in MySQL you would have to get the count of actors in each film as a sub query and join back to the base set.
SELECT title, b.cnt COUNT, actor.first_name, actor.last_name
FROM film
INNER JOIN film_actor
ON film.film_id = film_actor.film_id
INNER JOIN actor
ON film_actor.actor_id = actor.actor_id
INNER JOIN (SELECT film_ID, count(1) as cnt
FROM film_actor
GROUP BY film_ID) B
on film.film_ID = B.Film_ID
in databases which support window functions you could use a count(1) over (parttition by film.film_ID) as cnt
It may also be able to be achieved by using a group by with rollup without using an added join; but this creates an additional row with the total.
SELECT title, count(1) COUNT, actor.first_name, actor.last_name
FROM film
INNER JOIN film_actor
ON film.film_id = film_actor.film_id
INNER JOIN actor
ON film_actor.actor_id = actor.actor_id
on film.film_ID = B.Film_ID
GROUP BY title with rollup
I am trying to find the correct SQL to perform my task. I am trying to find the count of all actors that all act in the same movie. For all the movies. My SQL statement to fetch the film title and the first and last name of each actor is.
SELECT title, actor.first_name, actor.last_name,
FROM film
INNER JOIN film_actor ON film.film_id = film_actor.film_id
INNER JOIN actor ON film_actor.actor_id = actor.actor_id
ORDER BY film.title
My database returns this :
As you can see there are 10 actors belonging to the movie title ACADEMY DINOSAUR. What is the SQL that would provide me with a number of actors for each film?
Your SQL can be like this
SELECT title, count(1) COUNT
FROM film
INNER JOIN film_actor ON film.film_id = film_actor.film_id
INNER JOIN actor ON film_actor.actor_id = actor.actor_id
GROUP BY title
Pls try this
select tt.title, count(1) from (
SELECT title, actor.first_name, actor.last_name,
FROM film
INNER JOIN film_actor ON film.film_id = film_actor.film_id
INNER JOIN actor ON film_actor.actor_id = actor.actor_id
) tt group by tt.title
ORDER BY tt.title
I am writing a query to give actor id, first name, and last name for all actors who have never appeared in a film rated ‘PG’.
Here is what I've done. Can anyone tell me what I did wrong, please?
select distinct actor.actor_id, actor.first_name, actor.last_name
from actor, film, film_actor
where NOT exists
(Select distinct actor.actor_id,actor.first_name,actor.last_name
from actor,film_actor,film
where actor.actor_id = film_actor.actor_id
and film_actor.film_id = film.film_id
and film.rating = 'PG');
The not exists test for a condition and if the condition is true (exists) return false (not exists)
then in you case you get correctly no result
could be you need the actors not in you select
select actor.actor_id, actor.first_name, actor.last_name
from actor
where actor.id NOT in
(Select distinct actor.actor_id
from actor,film_actor,film
where actor.actor_id = film_actor.actor_id
and film_actor.film_id = film.film_id
and film.rating = 'PG');
Following up from the answer above, the line "actor.actor_id = film_actor.actor_id" inside the nested query is not necessary to get the same results. Shorter version:
select distinct a.actor_id, a.first_name, a.last_name from actor a where actor_id NOT IN (select distinct fa.actor_id from film_actor fa, film f where fa.film_id = f.film_id AND f.rating = 'PG');
I am new to MySQL; I am using SAS, and my brain is twisted in SAS style.
So, even I think I saw people asked questions similar to mine, I still cannot make sense out of the answers they received. I apologize for it.
I have 2 tables:
film_category containing columns:
category_id,film_id,
, film_actor containing columns
actor_id, film_id.
I joined them on film_id
. The question is:
What are the most popular actors in each film category?
There are 16 categories, 200 actors, 1000 films.
SELECT film_actor.actor_id,MAX(COUNT(actor_id))
FROM film_actor JOIN film_category
ON film_actor.film_id = film_category.film_id
GROUP BY film_category;
Sure enough, I've got error 1111, as soon as I added MAX...
Please let me know, if my question is not clear.
Thank you!
-Vera
This is your query:
SELECT fa.actor_id, MAX(COUNT(fa.actor_id))
FROM film_actor fa JOIN
film_category fc
ON fa.film_id = fc.film_id
GROUP BY fc.film_category;
This is invalid, because you cannot nest aggregation functions.
To do what you want, use a subquery and clever aggregation:
select film_category, max(numfilms) as maxnumfilms,
substring_index(group_concat(actor_id order by numfilms desc), ',', 1) as actor_id
from (select fc.film_category, fa.actor_id, count(*) as numfilms
from film_actor fa join
film_category fc
on fa.film_id = fc.film_id
group by fc.film_category, fa.actor_id
) ac
group by film_category;
Most occurring actor:
SELECT category_id AS cid,
(SELECT actor_id FROM
film_actor JOIN film_category
ON film_actor.film_id = film_category.film_id
WHERE category_id = cid
GROUP BY actor_id
ORDER BY COUNT(*) DESC
LIMIT 0,1) AS topActor
FROM film_actor JOIN film_category
ON film_actor.film_id = film_category.film_id
GROUP BY category_id ;