sql >> Databasteknik >  >> RDS >> Mysql

MySQL bästa N-resultat med kopplingstabeller

jag tror jag löser det :)

Först här är en lösning baserad på hur du började. Men det finns en hake som jag inte kunde lösa för att visa exakt 3 (eller vilket nummer du än väljer, jag väljer 3 till exempel) rad för varje person_id. Problemet är att lösningen är baserad på att räkna hur många rader som finns med rating_average större än nuvarande rad. Så om du har 5 samma högsta värde kan du välja att visa alla 5 eller att inte visa dem alls och det är inte bra. Så här är hur du gör det... (det här är givetvis ett exempel där om du har 4 toppvärden så visar du dem alla (jag tror att det inte är meningsfullt att inte visa data))...

 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

Viktigt: Denna lösning kan fungera (för att visa exakt 3 rader för varje person) om du inte har värde som upprepar det själv... Här är fiolen http://sqlfiddle.com/#!9/eb0fd/64 du kan se problemet där person_id är 1!

Efter det spelade jag lite mer och fick det att fungera precis som du ville i frågan tror jag. Här är en kod för det:

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

Här är fiolen för den där http://sqlfiddle.com/#!9/eb0fd/65 ...

GL!

P.S. förlåt för min engelska hoppas att du kunde förstå vad jag pratade om...




  1. Utföra replikeringstopologiändringar för PostgreSQL

  2. Skapa ett relaterat eller liknande inlägg med PHP &MySQL

  3. hoppa över kopiering till tmp-tabell på disk mysql

  4. Byt namn på tabell med mellanslag mysql