sql >> Base de Datos >  >> RDS >> Mysql

Resultados de MySQL Greatest N con tablas de unión

creo que lo resuelvo :)

Primero, aquí hay una solución basada en la forma en que comenzó. Pero hay un problema que no pude resolver para mostrar exactamente 3 (o cualquier número que elija, elijo 3, por ejemplo) fila para cada person_id. El problema es que la solución se basa en contar cuántas filas hay con rating_average mayor que la fila actual. Entonces, si tiene 5 valores máximos iguales, puede optar por mostrar los 5 o no mostrarlos en absoluto y eso no es bueno. Así que esta es la forma de hacerlo... (por supuesto, este es un ejemplo en el que si tiene 4 valores principales, los muestra todos (creo que no tiene ningún sentido no mostrar los datos))...

 SELECT t1.person_id, t1.credit_id, t1.media_id, t1.rating_average
 FROM (SELECT p.id AS person_id, c.id AS credit_id, m.id AS media_id, 
              m.rating_average AS rating_average
       FROM person p
       INNER JOIN credit c ON c.person_id = p.id
       INNER JOIN media m ON m.id = c.media_id) as t1
 WHERE (SELECT COUNT(*) 
       FROM (SELECT p.id AS person_id, c.id AS credit_id, m.id AS media_id, 
                    m.rating_average AS rating_average
             FROM person p
             INNER JOIN credit c ON c.person_id = p.id
             INNER JOIN media m ON m.id = c.media_id) AS t2
       WHERE t2.person_id = t1.person_id AND t2.rating_average > t1.rating_average) < 3
 ORDER BY person_id ASC, rating_average DESC

Importante: Esta solución puede funcionar (para mostrar 3 filas exactas para cada persona) si no tiene un valor que se repita... Aquí está el Fiddle http://sqlfiddle.com/#!9/eb0fd/64 ¡puedes ver el problema donde person_id es 1!

Después de eso, jugué un poco más y lo hice funcionar como querías en la pregunta, creo. Aquí hay un código para eso:

SET @num := 0, @person := 0;

SELECT person_id, credit_id, media_id, rating_average, rowNumber 
FROM (SELECT t1.person_id, t1.credit_id, t1.media_id, t1.rating_average,
             @num := if(@person = t1.person_id, @num + 1, 1) AS rowNumber,
             @person := t1.person_id
      FROM (SELECT p.id AS person_id, c.id AS credit_id, m.id AS media_id, 
                   m.rating_average AS rating_average
            FROM person p
            INNER JOIN credit c ON c.person_id = p.id
            INNER JOIN media m ON m.id = c.media_id
            ORDER BY p.id ASC, m.rating_average DESC) as t1) as t2
 WHERE rowNumber <= 3

Aquí está el violín para eso http://sqlfiddle.com/#!9/eb0fd/65 ...

GL!

P. D. Perdón por mi inglés, espero que puedas entender de lo que estaba hablando...