Top 10 Películas Más Rentadas: Consulta SQL Paso a Paso
Resumen
¿Cómo realizar un análisis de top diez con SQL?
Para muchas organizaciones, es importante identificar los elementos más destacados dentro de un conjunto de datos. En este contexto, comúnmente se utilizan las listas de "top diez" para resaltar las principales métricas de importancia, como las películas más rentadas de un catálogo. A través de este análisis, podemos llevar a cabo diferenciaciones útiles y estratégicas basadas en criterios específicos. A continuación, exploraremos cómo implementarlo utilizando SQL para obtener resultados precisos y bien organizados.
¿Cuál es el approach para el top diez de películas más rentadas?
Para identificar cuáles son las diez películas más rentadas, es importante conocer la estructura y relaciones dentro de la base de datos. En las bases de datos relacionales, rara vez un dato se obtiene de una tabla aislada; más bien, se requiere unir varias tablas para obtener la información completa. En este caso, es crucial tener claro cómo se relacionan las tablas que contienen información sobre rentas con las tablas que contienen las películas. Esto significa emplear uniones y clausulas específicas para organizar y filtrar los datos de manera eficiente.
SELECT p.película_id AS id, p.título,COUNT(r.renta_id)AS número_rentas
FROM rentas r
INNERJOIN inventarios i ON r.inventario_id = i.inventario_id
INNERJOIN películas p ON i.película_id = p.película_id
GROUPBY p.película_id
ORDERBY número_rentas DESCLIMIT10;
Esta consulta SQL nos proporciona los campos de ID de película, su título y el número total de rentas, permitiendo obtener una lista de las películas más populares.
¿Qué técnica utilizamos para asignar un índice de ranking?
Para presentar los datos con un índice que indique la posición de cada película dentro del top diez, se puede utilizar una función de ventana. Esta función ayuda a superar las limitaciones de los métodos tradicionales y asegura que el índice sea claro y utilizable en sistemas gráficos u otras presentaciones de datos.
SELECT ROW_NUMBER()OVER(ORDERBYCOUNT(r.renta_id)DESC)AS lugar, p.película_id AS id, p.título,COUNT(r.renta_id)AS número_rentas
FROM rentas r
INNERJOIN inventarios i ON r.inventario_id = i.inventario_id
INNERJOIN películas p ON i.película_id = p.película_id
GROUPBY p.película_id
ORDERBY número_rentas DESCLIMIT10;
La función ROW_NUMBER() genera un índice para cada fila basándose en el orden descendente del número de rentas, lo cual es especialmente útil para crear clasificaciones claras y directas.
¿Cómo garantizar que nuestra consulta sea eficiente y manejable?
Es fundamental que las consultas SQL sean optimizadas para asegurar su eficacia. Las prácticas para mejorar el rendimiento implican comprender las uniones necesarias y utilizar correctamente las funciones de agregado y ventana. A continuación, algunos consejos prácticos:
Conoce tu base de datos: Familiarízate con las tablas y sus relaciones.
Utiliza índices: Facilitan el acceso rápido a las filas correspondientes.
Minimiza el uso de alias: Reduce la carga cognitiva y mejora la claridad del código.
Aprovecha las funciones de ventana: Estas funciones son poderosas para realizar cálculos complejos sin afectar el rendimiento de la consulta.
Al seguir estas recomendaciones, tu consulta no solo será precisa y útil, sino que también estará optimizada para su uso en entornos de producción y reportes gráficos. ¡Sigue explorando e implementando más habilidades de SQL para mantenerte en la vanguardia del análisis de datos!
select
peliculas.pelicula_idas id, peliculas.titulo,count(1)as numero_rentas
from rentas
inner join inventarios on
rentas.inventario_id= inventarios.inventario_idinner join peliculas on
peliculas.pelicula_id= inventarios.pelicula_idgroup by
peliculas.pelicula_id, peliculas.tituloorder by
numero_rentas desc
limit 10;
Así es!
Por fin con esta clase pude entender exactamente para que sirven las Window function!! Graciass
Ohh yeah!
Una de sus varias funciones!
Pero algunas películas tienen el mismo número de rentas. Entonces deberían de quedar empatados en una misma posición, mientra que con esta solución no sucede esto.
En los casos que están empatados en vez de utilizar la función ROW_NUMBER(), se utilizaría la función la función DENSE_RANK()
Chequear también las funciones RANK() y como dice Alexander, DENSE_RANK().
Hice algunas modificaciones para un mejor resultado :)
-- Top 10 las peliculas mas rentadas
SELECT peliculas.pelicula_id AS id,
peliculas.titulo,
COUNT(*) AS numero_rentas,
-- Window function del top, si se repite el top tienen el mismo lugar
DENSE_RANK() OVER(ORDER BY COUNT(*) DESC) AS top
FROM rentas
JOIN inventarios
ON inventarios.inventario_id = rentas.inventario_id
JOIN peliculas
ON peliculas.pelicula_id = inventarios.pelicula_id
GROUP BY peliculas.pelicula_id
HAVING COUNT(*) > 24 -- Filtrando los 10 mas rentados
ORDER BY numero_rentas DESC
;
👾
Tambien se puede hacer algo asi para evitar el 24 como magic number y no tener tanta salida de datos para un dashboard
WITH top_10 AS(SELECTCOUNT(*)AS numero_rentas, p.tituloas titulo,dense_rank()over(order by count(*)desc)as top
FROM rentas as r
LEFTJOIN inventarios AS i ON i.inventario_id= r.inventario_idLEFTJOIN peliculas AS p ON p.pelicula_id= i.pelicula_idGROUPBY p.tituloORDERBY numero_rentas DESC)SELECT numero_rentas,string_agg(titulo,', '),ROW_NUMBER()OVER()FROM top_10
group by numero_rentas,top order by numero_rentas desc limit 10```
Podemos ahorrarnos unas lineas de código aplicando la sentencia WITH
WITH top_10 AS(SELECTCOUNT(*)AS numero_rentas, p.tituloFROM rentas as r
LEFTJOIN inventarios AS i ON i.inventario_id= r.inventario_idLEFTJOIN peliculas AS p ON p.pelicula_id= i.pelicula_idGROUPBY p.tituloORDERBY numero_rentas DESCLIMIT10)SELECT*,ROW_NUMBER()OVER()FROM top_10;
SELECT peliculas.pelicula_idAS id, peliculas.titulo,COUNT(*)AS numero_rentas,ROW_NUMBER()OVER(ORDERBYCOUNT(*)DESC)AS lugar
FROM rentas
INNERJOIN inventarios ON rentas.inventario_id= inventarios.inventario_idINNERJOIN peliculas ON inventarios.pelicula_id= peliculas.pelicula_idGROUPBY peliculas.pelicula_idORDERBY numero_rentas DESCLIMIT10;
Genial!!! Utilizar Window functions!! 👏🏻
para los que no entendieron, aqui dejo una explicación resumida de lo que se hizo.
Explicación del código:
Se utiliza ROW_NUMBER() para asignar un número secuencial a cada fila basado en el orden descendente de rentas.
Se selecciona el título de la película y se cuenta el número total de rentas utilizando COUNT(*).
Se realizan las uniones necesarias entre las tablas peliculas, inventarios, y rentas para obtener la información completa.
Se agrupa por la columna peliculas.pelicula_id para contar las rentas por película.
Se ordena el resultado por el número de rentas de forma descendente.
Se utiliza la cláusula LIMIT 10 para obtener solo las primeras diez filas.
gracias, buen aporte :)
Desde el 8 al 16, todos tienen 31 rentas.
En este caso siento que es mas útil el dense_rank.
...
Gracias por el aporte, no había visto ese detalle.
No hay de qué..!
27. Top 10
Datapoints: cada sección.
SELECT peliculas.pelicula_id AS id, peliculas.titulo,COUNT(*)AS numero_rentas, ROW_NUMBER ()OVER(ORDERBYCOUNT(*)DESC)AS lugar
FROM rentas
INNERJOIN inventarios ON rentas.inventario_id = inventarios.inventario_id
INNERJOIN peliculas ON inventarios.pelicula_id = peliculas.pelicula_id
GROUPBY peliculas.pelicula_id
ORDERBY numero_rentas DESCLIMIT10;
¿Qué criterio deberían usar para decidir sobre que table se hace el "FROM"?
Por ejemplo yo lo hice a partirt de la tabla platzi.peliculas
SELECT p.pelicula_idAS id, p.tituloASPelícula,COUNT(r.renta_id)ASTotalFROM peliculas AS p
JOIN inventarios AS i ON i.pelicula_id= p.pelicula_idJOIN rentas AS r ON r.inventario_id= i.inventario_idGROUPBY p.pelicula_id, p.tituloORDERBYTotalDESCLIMIT10;```SELECT 	p.pelicula\_id AS id,	p.tituloASPelícula,	COUNT(r.renta\_id)ASTotalFROM peliculas AS p
	JOIN inventarios AS i ON i.pelicula\_id = p.pelicula\_id
	JOIN rentas AS r ON r.inventario\_id = i.inventario\_id
GROUPBY 	p.pelicula\_id,	p.tituloORDERBYTotalDESCLIMIT10;
Yo lo hice de la siguiente manera y salió más práctico.
AS numero_rentas
ROW_NUMBER()OVER(ORDERBYCOUNT(*)DESEC)AS lugar
FROM rentas
INNERJOING inventarios on
rentas.inventario_id= inventarios.inventario_idINNERJOING peliculas on
peliculas.pelicula_id= inventarios.pelicula_idGROUPBY peliculas.pelicula_id, peliculas.tituloORDERBY numero_rentas DESCLIMIT10;
Ingeniero te falto la coma en
COUNT() AS numero_rentas,
también esta mal escrito DESEC ES DESC
ROW_NUMBER() OVER(
ORDER BY COUNT() DESEC
) AS lugar
Empezando con este prometedor curso :D
SELECT
peliculas.pelicula_id AS id,
peliculas.titulo,
COUNT(*) AS numero_rentas,
ROW_NUMBER() OVER (
ORDER BY COUNT(*) DESC, peliculas.titulo
) AS lugar
FROM rentas
INNER JOIN inventarios ON rentas.inventario_id = inventarios.inventario_id
INNER JOIN peliculas ON inventarios.pelicula_id = peliculas.pelicula_id
GROUP BY peliculas.pelicula_id
ORDER BY numero_rentas DESC
LIMIT 10;
¿Cómo obtener las 10 películas con más rentas?
WITH
amount_rentas_movies AS (
SELECT i.pelicula_id, COUNT(*) AS amount_rentas
FROM rentas r JOIN inventarios i ON r.inventario_id = i.inventario_id
GROUP BY i.pelicula_id
),
temp_table AS (
SELECT pelicula_id, amount_rentas,
ROW_NUMBER() OVER(ORDER BY amount_rentas DESC) AS ranking
FROM amount_rentas_movies
)
SELECT p.pelicula_id, p.titulo
FROM temp_table t JOIN peliculas p ON t.ranking < 11 AND t.pelicula_id = p.pelicula_id
;
Obtengo la cantidad de rentas por cada película con la tabla temporal amount_rentas_movies.
Asigno un ranking único a cada película con la window function ROW_NUMBER , en función de su cantidad de rentas.
Finalmente, filtro aquellos registros cuyo ranking sea mayor a 10.
Es importante la distinción entre ROW_NUMBER y [DENSE_RANK | RANK], porque las funciones de ranking le asignan un mismo id a aquellos registros que tengan un mismo valor para una columna particular, entonces esto puede causar que a la hora de hacer filtrado ranking < 11, se retornen más de 10 filas.
🏆 ¡Creando un Ranking con ROW_NUMBER()! 📊
Aquí les muestro una forma profesional de crear un ranking de las películas más rentadas. La clave es el uso de la función de ventana ROW_NUMBER(), que nos permite asignar un número de posición sin perder el detalle de la tabla.
¿Cómo funciona la magia?
ROW_NUMBER() OVER(ORDER BY ...): Esta es la función de ventana. Le decimos que cuente y asigne un número de fila para cada película. El número 1 es para la primera, el 2 para la segunda, y así sucesivamente.
ORDER BY: Dentro del OVER(), le indicamos cómo queremos que se ordenen las filas para el ranking. En este caso, usamos COUNT(*) DESC para que la película con más rentas reciba el puesto número 1.
GROUP BY: Agrupamos por id y titulo para que el conteo de rentas se haga por cada película. Este paso es fundamental para poder usar el COUNT(*) correctamente.
¡Es una herramienta súper potente para el análisis de datos, ya que te da un ranking preciso en una sola consulta! 😉
En mi caso, hice la consulta antes de ver la lección y después de verla hice varías mejoras sobre todo en el sentido de hacerla mas concisa y obtener el mismo resultado con el menor número de líneas.
No me parece deseable usar DENSE_RANK, porque terminas con un top10 de mas de 100 películas y con RANK terminas con un top10 que no llega a numerar hasta el 10.
En un caso de la vida real, simplemente numeras los primeros 10 y si hace falta, haces un desempate con base en otros criterios, que en este escenario no se establecieron.
SELECTROW_NUMBER()OVER(ORDERBYCOUNT(*)DESC)AS ranking_renta, p.titulo,COUNT(*)AS no_rentas
FROM rentas r
JOIN inventarios i USING(inventario_id)JOIN peliculas p USING(pelicula_id)GROUPBY pelicula_id
LIMIT10;