Soluciones varias

-- Clientes de España o Argentina

select customer.* from country join city on country.country_id=city.country_id
join address on city.city_id=address.city_id
join customer on address.address_id=customer.address_id
where country in ('spain','argentina');

-- Ventas totales por empleado

select staff.*, sum(amount) total from staff 
join payment on staff.staff_id=payment.staff_id
group by staff.staff_id;

-- Películas en las que han trabajado más de 10 actores

select film.*, count(actor_id) actores from film 
join film_actor on film.film_id=film_actor.film_id
group by film_id
having actores>10;

-- El título de la película que más se ha alquilado (en número de alquileres)

-- Solución decente pero no correcta
-- ¿Por qué? Porque si hay varias películas que tengan el mismo número
-- de alquileres solo saldrá una
select title, count(rental_id) alquileres from film 
join inventory on film.film_id=inventory.film_id
join rental on inventory.inventory_id=rental.inventory_id
group by film.film_id
order by alquileres desc
limit 1;

-- ¿Cual sería la solución correcta?
-- Buscar el máximo de alquileres
-- Selecciona las películas que tengan ese número de alquileres

select title, count(rental_id) alquileres from film 
join inventory on film.film_id=inventory.film_id
join rental on inventory.inventory_id=rental.inventory_id
group by film.film_id
having alquileres=(
	select count(rental_id) total from film 
	join inventory on film.film_id=inventory.film_id
	join rental on inventory.inventory_id=rental.inventory_id
	group by film.film_id
	order by total desc
	limit 1);
    
-- El título de la película que más dinero ha dado (en suma de importe)

-- Solución decente pero no del todo correcta
select title, sum(amount) importe from film 
join inventory on film.film_id=inventory.film_id
join rental on inventory.inventory_id=rental.inventory_id
join payment on rental.rental_id=payment.rental_id
group by film.film_id
order by importe desc
limit 1;

-- SOlución teniendo en cuenta empates

select title, sum(amount) importe from film 
join inventory on film.film_id=inventory.film_id
join rental on inventory.inventory_id=rental.inventory_id
join payment on rental.rental_id=payment.rental_id
group by film.film_id
having importe=(
	select sum(amount) importe from film 
	join inventory on film.film_id=inventory.film_id
	join rental on inventory.inventory_id=rental.inventory_id
	join payment on rental.rental_id=payment.rental_id
	group by film.film_id
	order by importe desc
	limit 1);
    
-- Los 5 actores que han trabajado en menos películas

select actor.*, count(film_id) peliculas from actor 
join film_actor on actor.actor_id=film_actor.actor_id
group by actor_id
order by peliculas
limit 5;

-- Posible otra solución también imperfecta pero quizá más correcta

select actor.*, count(film_id) peliculas from actor 
join film_actor on actor.actor_id=film_actor.actor_id
group by actor.actor_id
having peliculas<=(
	select max(peliculas) from (
		select count(film_id) peliculas from actor 
		join film_actor on actor.actor_id=film_actor.actor_id
		group by actor.actor_id
		order by peliculas
		limit 5) as temp
        );
        
-- Encontrar los clientes que hayan gastado más de 100 dólares

select customer.*, sum(amount) total from customer 
join payment on customer.customer_id=payment.customer_id
group by customer_id
having total>100;

-- Actores que no hayan trabajado en películas para niños o familiares

-- Consulta de división: primero miro los que sí y luego los que no
select * from actor
where actor_id not in (
	select actor_id from category
	join film_category on category.category_id=film_category.category_id
	join film on film_category.film_id=film.film_id
	join film_actor on film.film_id=film_actor.film_id
	where name in ('children','family'));

-- Actores que hayan trabajado en películas que no se hayan alquilado nunca

select distinct actor.* from actor join film_actor on actor.actor_id=film_actor.actor_id
where film_id not in (
select film.film_id from film join inventory on film.film_id=inventory.film_id
join rental on inventory.inventory_id=rental.inventory_id);

select distinct actor.* from actor 
join film_actor on actor.actor_id=film_actor.actor_id
join film on film_actor.film_id=film.film_id
left join inventory on film.film_id=inventory.film_id
left join rental on inventory.inventory_id=rental.inventory_id
where rental_id is null;

-- Clientes que han hecho un total de pagos por encima de la media.
-- Divide y vencerás
-- Calculo el total de pagos po cliente
select customer.*, sum(amount) pagos from customer
join payment on customer.customer_id=payment.customer_id
group by customer_id;
-- calculo la media sobre esta consulta
select avg(pagos) media from (
select customer.*, sum(amount) pagos from customer
join payment on customer.customer_id=payment.customer_id
group by customer_id) as temp;
-- filtro los clientes cuyo total esté por encima de la media
select customer.*, sum(amount) pagos from customer
join payment on customer.customer_id=payment.customer_id
group by customer_id
having pagos>(select avg(pagos) media from (
	select customer.*, sum(amount) pagos from customer
	join payment on customer.customer_id=payment.customer_id
	group by customer_id) as temp);

-- con vistas
create view pagos_por_cliente as
select customer.*, sum(amount) pagos from customer
join payment on customer.customer_id=payment.customer_id
group by customer_id;

select * from pagos_por_cliente
where pagos>(select avg(pagos) media from pagos_por_cliente);

-- Clientes que no han alquilado documentales (‘documentary’)
-- Primero los que alquilan

select * from customer join rental using (customer_id)
join inventory using (inventory_id)
join film using (film_id)
join film_category using (film_id)
join category using (category_id)
where name='documentary';

-- Pues esos no, los otros
select * from customer
where customer_id not in (
	select customer_id from customer join rental using (customer_id)
	join inventory using (inventory_id)
	join film using (film_id)
	join film_category using (film_id)
	join category using (category_id)
	where name='documentary');

Publicado por

Juan Pablo Fuentes

Formador de programación y bases de datos