Упростите медленный MySQL запрос

0

Этот запрос вычисляет столбцы free, plus, score и total основано на столбце COUNT в подзапросе.

SELECT movie_title,movie_id,MAX(x.free_cnt) as free, MAX(x.plus_cnt) as plus, 
                (MAX(x.free_cnt) + (MAX(x.plus_cnt)*3)) AS score, (MAX(x.free_cnt) + MAX(x.plus_cnt)) AS total
                    FROM (
                        SELECT b.id as movie_id, b.movie_title as movie_title, COUNT(*) AS free_cnt, 0 as plus_cnt
                        FROM subtitles_request a1
                        LEFT JOIN movies b on a1.movie_id=b.id
                        JOIN users c on c.email=a1.email
                        WHERE c.subsc_status='0'
                        GROUP BY b.movie_title
                        UNION ALL

                        SELECT d.id as movie_id, d.movie_title as movie_title,  0 as free_cnt, COUNT(*) AS plus_cnt
                        FROM subtitles_request a2
                        LEFT JOIN movies d on a2.movie_id=d.id
                        JOIN users e on e.email=a2.email
                        WHERE e.subsc_status='1'
                        GROUP BY d.movie_title

                    ) AS x
                    GROUP BY movie_title
                    ORDER BY total DESC
                    LIMIT 10

Это медленное выполнение, и мне интересно, есть ли в любом случае я могу упростить или изменить запрос, чтобы ускорить работу. Я не могу вычислить free, plus, score, total столбцы вне запроса из-за возможности заказа. Также я могу включить дату.

В любом случае, чтобы упростить этот запрос?

Теги:

2 ответа

1
Лучший ответ

Попробуй это:

    SELECT b.movie_title, x.movie_id, MAX( x.free_cnt ) AS free, MAX( x.plus_cnt ) AS plus, 
           ( MAX( x.free_cnt ) + ( MAX( x.plus_cnt ) * 3 ) ) AS score, ( MAX( x.free_cnt ) + MAX( x.plus_cnt ) ) AS total
    FROM ( SELECT a.movie_id,
                  SUM( IF( c.subsc_status = '0', 1, 0 ) ) AS free_cnt, 
                  SUM( IF( c.subsc_status = '1', 1, 0 ) ) AS plus_cnt
           FROM subtitles_request a1
           JOIN users c on c.email=a1.email
           WHERE c.subsc_status in ('0','1')
           GROUP BY a.movie_id
         ) AS x
    LEFT JOIN movies b on x.movie_id = b.id
    GROUP BY movie_title, movie_id
    ORDER BY total DESC
    LIMIT 10

Может быть, я немного упростил. Более того, я не привык группировать только некоторые из неагрегатных полей, поэтому я добавил movie_id к тому, что сгруппировано и, таким образом, немного изменил ваш запрос (если у двух фильмов было одно и то же имя, но с другим идентификатором, тогда только один из id будет возвращен в вашем исходном запросе, но я предполагаю (будучи новичком MySQL, я действительно не знаю), подсчеты были бы для обоих из них взяты вместе).

HTH, Set

  • 0
    спасибо, это прекрасно.
0

Ну, я проверил ваш подзапрос:

SELECT b.id as movie_id, b.movie_title as movie_title, COUNT(*) AS free_cnt, 0 as plus_cnt
FROM subtitles_request a1
LEFT JOIN movies b on a1.movie_id=b.id
JOIN users c on c.email=a1.email
WHERE c.subsc_status='0'
GROUP BY b.movie_title
UNION ALL

SELECT d.id as movie_id, d.movie_title as movie_title,  0 as free_cnt, COUNT(*) AS plus_cnt
FROM subtitles_request a2
LEFT JOIN movies d on a2.movie_id=d.id
JOIN users e on e.email=a2.email
WHERE e.subsc_status='1'
GROUP BY d.movie_title

Заявление рядом с "UNION ALL" можно заменить одним утверждением с условием в c.subsc_status IN('0','1'). И вы можете попробовать использовать оператор CASE WHEN в 0 as free_cnt, COUNT(*) AS plus_cnt, точно так же, как IFNULL((CASE WHEN e.subsc_status='1' THEN COUNT(*)),0) as free_cnt. Это не сложный оператор sql, я не думаю, что потребуется слишком много времени для запроса. Есть ли слишком много данных? На самом деле, я тоже новичок, но у меня просто есть опыт в этом. Пожалуйста, простите меня, если это не сработает.

Ещё вопросы

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