Как ограничить список в Python, чтобы показать N записей для каждой уникальной строки?

0

Я пытаюсь ограничить вывод mysql запроса, чтобы показывать только верхние записи N для каждого жанра. Это мой код:

def selectTopNactors(n):

# Create a new connection
con=connection()

# Create a cursor on the connection
cur=con.cursor()
#execute query
int(n)
sql ="""SELECT g.genre_name, a.actor_id,COUNT(mg.genre_id) as num_mov
FROM actor as a, role as r,movie as m,genre as g, movie_has_genre as mg
WHERE a.actor_id = r.actor_id AND m.movie_id = r.movie_id
      AND m.movie_id = mg.movie_id AND g.genre_id = mg.genre_id
      AND (g.genre_id, m.movie_id) IN (SELECT g.genre_id, m.movie_id
       FROM movie as m, genre as g, movie_has_genre as mg
       WHERE m.movie_id = mg.movie_id AND mg.genre_id = g.genre_id 
       ORDER BY g.genre_id)
       GROUP BY g.genre_name, a.actor_id
       ORDER BY g.genre_name, COUNT(*) desc """

cur.execute(sql)

results = cur.fetchall()


listab = []
listac = []
for row in results:
     lista = []
     lista.append(row[0])
     lista.append(row[1])
     lista.append(row[2])
     listab = tuple(lista)
     listac.append(listab)
head = ("genreName","actorId","numberOfMovies")    
listac.insert(0,head) 


print (n)
con.commit()
return listac

И список, который возвращает его, является огромным (6000+) записями, поэтому я хочу показать только N записей для каждого жанра. возвращенный список здесь

  • 1
    Предложение: исключите синтаксис запятой старой школы для операций объединения, используйте вместо этого ключевое слово JOIN и переместите предикаты объединения из WHERE в соответствующее предложение ON .
  • 0
    @spencer7593 spencer7593 спасибо за ваш ответ, но это не сработает для меня, потому что мне нужен пользовательский ввод для N, поэтому я думаю, что хитрость будет в части Python.
Показать ещё 2 комментария
Теги:
python-3.x
pymysql

1 ответ

1

В версии MySQL до 8.0 мы можем эмулировать аналитические функции с использованием пользовательских переменных в тщательно обработанных запросах. Обратите внимание, что мы зависим от поведения пользовательских переменных, которые не гарантируются (задокументированы в Справочном руководстве по MySQL).

SELECT @rn := IF(c.genre_name=@prev_genre,@rn+1,1) AS rn
     , @prev_genre := c.genre_name                 AS genre_name
     , c.actor_id                                  AS actor_id
     , c.num_mov                                   AS num_mov
  FROM ( SELECT @prev_genre := NULL, @rn := 0 ) i
 CROSS 
  JOIN ( SELECT g.genre_name
              , a.actor_id
              , COUNT(1) AS num_mov
           FROM actor a
           JOIN role r
             ON r.actor_id = a.actor_id
           JOIN movie m
             ON m.movie_id = r.movie_id
           JOIN movie_has_genre mg
             ON mg.movie_id = m.movie_id
           JOIN genre g
             ON g.genre_id = mg.genre_id
          GROUP
             BY g.genre_name
              , a.actor_id
          ORDER
             BY g.genre_name
              , COUNT(1) DESC
              , a.actor_id
       ) c
 ORDER
    BY c.genre_name
     , c.num_mov DESC
     , c.actor_id
HAVING rn <= 4

Литерал 4 в конце запроса представляет значение N в вопросе.

В MySQL 8.0 мы можем использовать вновь введенные аналитические функции, чтобы получить эквивалентный результат:

SELECT ROW_NUMBER() OVER(PARTITION BY c.genre_name ORDER BY c.num_mov DESC, c.actor_id)
       AS rn
     , c.genre_name                                 AS genre_name
     , c.actor_id                                   AS actor_id
     , c.num_mov                                    AS num_mov
  FROM ( SELECT g.genre_name
              , a.actor_id
              , COUNT(1) AS num_mov
           FROM actor a
           JOIN role r
             ON r.actor_id = a.actor_id
           JOIN movie m
             ON m.movie_id = r.movie_id
           JOIN movie_has_genre mg
             ON mg.movie_id = m.movie_id
           JOIN genre g
             ON g.genre_id = mg.genre_id
          GROUP
             BY g.genre_name
              , a.actor_id
          ORDER
             BY g.genre_name
              , COUNT(1) DESC
              , a.actor_id
       ) c
 ORDER
    BY c.genre_name
     , c.num_mov DESC
     , c.actor_id
HAVING rn <= 4
  • 0
    Спасибо за ваш аналитический и хороший ответ, у меня mySql 8.0 и mySql Workbench 8.0, я получаю ошибку xytax, я думаю, что RowNumber () не распознается mySql.
  • 0
    dev.mysql.com/doc/refman/8.0/en/… Я еще не использовал аналитические функции в MySQL 8.0 ... приведенный пример - мое лучшее предположение. Метод пользовательских переменных работает в MySQL 5.6 и 5.7, я ожидаю, что он все еще будет работать в MySQL 8.0.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню