una transponer tabla seleccionar registros por pivote otra mostrar invertir filas fila ejemplos datos crear copiar como columnas campos mysql

transponer - Seleccionando filas de una tabla usando valores obtenidos de otra tabla MYSQL



seleccionar campos de una tabla mysql (5)

Consulta:

SELECT t1.* FROM film t1 WHERE EXISTS (SELECT filmid FROM film_rating_report t2 WHERE t2.rating = ''GE'' AND t2.filmid = t1.id);

Actualmente tengo 2 tablas mysql en mi base de datos

Film and Film_Ratings_Report

La clave principal de Film es filmid que se utiliza para identificar las calificaciones de la película en la tabla Film_Ratings_Report .

Me gustaría saber si es posible usar una consulta MYSQL solo para buscar en la tabla de clasificación y recopilar todas las ID de película que cumplan con ciertos criterios y luego usar las ID seleccionadas para obtener los títulos de la película. A continuación se muestra la consulta MYSQL que estoy usando y que no funciona:

SELECT * FROM film UNION SELECT filmid FROM film_rating_report WHERE rating = ''GE'' LIMIT 0,0

Soy relativamente verde para MYSQL y agradecería cualquier ayuda en esto.

Gracias por adelantado


Creo que esto funcionará, pensé sin conocer su estructura de base de datos (considere dar SHOW CREATE TABLE en sus tablas), no tengo forma de saberlo con seguridad:

SELECT film.* FROM (film) LEFT JOIN film_rating_report ON film.filmid = film_rating_report.filmid AND film_rating_report.rating = ''GE'' WHERE film_rating_report.filmid IS NOT NULL GROUP BY film.filmid

(El WHERE film_rating_report.filmid IS NOT NULL evita que las líneas que no tienen la calificación que está buscando se coló, agregué GROUP BY al final porque film_rating_report puede coincidir más de una vez; no estoy seguro, ya que tengo visibilidad de los datos almacenados. en eso)


La solución preferida para esto es usar join y no olvide group by para que no tenga líneas duplicadas:

select film.* from film join film_rating_report on film.filmid = film_rating_report.filmid and rating = ''GE'' group by film.filmid

EDITAR: según lo señalado correctamente por @ypercube, me equivoqué al afirmar que el rendimiento de join & group es mejor que usar subconsultas con exists o in todo lo contrario.


Parece que desea una semi-join , por ejemplo, una unión donde solo se necesitan datos de una de las 2 tablas unidas. En este caso, todas las filas de la film para las que hay una fila coincidente en film_rating_report que tiene la condición deseada ( rating = ''GE'' ).

Esto no es exactamente equivalente a una combinación habitual porque incluso si hay 2 (o más) filas en la segunda tabla (2 clasificaciones de una película, ambas con ''GE'' ), queremos que la película se muestre una vez, no dos veces (o más veces) como se mostraría con una combinación habitual.

Hay varias formas de escribir una semi-unión y las más populares son:

  • utilizando una subconsulta correlacionada EXISTS ( la respuesta de @Justin ):

    SELECT t1.* FROM film t1 WHERE EXISTS (SELECT filmid FROM film_rating_report t2 WHERE t2.rating = ''GE'' AND t2.filmid = t1.id);

  • utilizando una subconsulta IN (no correlacionada) ( respuesta de @SG 86 ):
    (esto debe usarse con sumo cuidado, ya que puede generar resultados inesperados, o ninguno en absoluto, si las columnas que se unen (las dos filmid en este caso) son Nullable)

    SELECT * FROM film WHERE id IN ( SELECT filmid FROM film_rating_report WHERE rating = ''GE'' );

  • usando un JOIN habitual con GROUP BY para evitar las filas duplicadas en los resultados ( respuesta de @Tomas ):
    (y tenga en cuenta que este uso específico de GROUP BY funciona en MySQL y en las versiones recientes de Postgres, si alguna vez desea escribir una consulta similar en otro DBMS, deberá incluir todas las columnas: GROUP BY f.filmid, f.title, f.director, ... )

    SELECT f.* FROM film AS f JOIN film_rating_report AS frr ON f.filmid = frr.filmid WHERE frr.rating = ''GE'' GROUP BY f.filmid ;

  • Una variación en la respuesta de @Tomas''es, donde GROUP BY se realiza en una tabla derivada y luego en JOIN :

    SELECT f.* FROM film AS f JOIN ( SELECT filmid FROM film_rating_report WHERE rating = ''GE'' GROUP BY filmid ) AS frr ON f.filmid = frr.filmid ;

Cuál usar, depende del RDBMS y la versión específica que esté utilizando (por ejemplo, las subconsultas IN deben evitarse en la mayoría de las versiones de MySQL, ya que pueden producir planes de ejecución ineficientes), sus tamaños de tablas, distribución, índices, etc.

Por lo general, prefiero la solución EXISTS , pero nunca está de más probar primero las distintas consultas con los tamaños de tabla que tiene o espera tener en el futuro y tratar de encontrar la mejor combinación de índices de consulta para su caso.

Adición: si hay una restricción única en la film_rating_report (filmid, rating) , lo que significa que ninguna película obtendrá dos calificaciones iguales, o si hay una restricción única aún más estricta (pero más plausible) en film_rating_report (filmid) que significa que cada película tiene a lo sumo una calificación, puede simplificar las soluciones de JOIN para (y deshacerse de todas las demás consultas):

SELECT f.* FROM film AS f JOIN film_rating_report AS frr ON f.filmid = frr.filmid WHERE frr.rating = ''GE'' ;


SELECT * FROM film WHERE id IN (SELECT filmid FROM film_rating_report WHERE rating = ''GE'');

Deberia trabajar