2012-01-04 2 views
2

Я следующий запрос MySQL:Как реорганизовать этот запрос MySQL?

(SELECT c.Channel as name, count(*) as total_episode 
FROM (
    SELECT a.aid, a.vid 
    FROM videoItem v INNER JOIN aid2vid a USING(vid) 
    GROUP BY a.aid 
) a1 INNER JOIN channelListingItem c USING(aid) 
GROUP BY c.Channel 
) 
UNION 
(SELECT c1.Channel as name, 0 as total_episode 
FROM channelListingItem c1 LEFT JOIN (
    SELECT c.Channel FROM (
     SELECT a.aid, a.vid 
     FROM videoItem v INNER JOIN aid2vid a USING(vid) 
     GROUP BY a.aid 
    ) a1 INNER JOIN channelListingItem c USING(aid) 
    GROUP BY c.Channel 
) c2 USING(Channel) 
WHERE c2.Channel is null 
GROUP BY name 
); 

В принципе, что это заявление делает это, чтобы получить правильное количество эпизодов в каждом канале & присвоить ноль для каналов без VID в последующей таблице (videoItem).

Обратите внимание, что

SELECT a.aid, a.vid 
FROM videoItem v 
INNER JOIN aid2vid a USING(vid) 
GROUP BY a.aid 

дублируется дважды и от объяснить это заявление MySQL я не вижу MySQL повторно использовать результат запроса.

+----+--------------+------------+------+----------+---------+---------+----------+------+---------------------------------+ 
| id | select_type | table  | type | pos_keys | key  | key_len | ref  | rows | Extra       | 
+----+--------------+------------+------+----------+---------+---------+----------+------+---------------------------------+ 
| 1 | PRIMARY  | <derived2> | ALL | NULL  | NULL | NULL | NULL  | 313 | Using temporary; Using filesort | 
| 1 | PRIMARY  | c   | ALL | idx_vid | NULL | NULL | NULL  | 616 | Using where; Using join buffer | 
| 2 | DERIVED  | a   | ALL | vid  | NULL | NULL | NULL  | 1015 | Using temporary; Using filesort | 
| 2 | DERIVED  | v   | ref | idx_vid | idx_vid | 32  | db.a.vid | 10 | Using index      | 
| 3 | UNION  | c1   | ALL | NULL  | NULL | NULL | NULL  | 616 | Using temporary; Using filesort | 
| 3 | UNION  | <derived4> | ALL | NULL  | NULL | NULL | NULL  | 28 | Using where; Not exists   | 
| 4 | DERIVED  | <derived5> | ALL | NULL  | NULL | NULL | NULL  | 313 | Using temporary; Using filesort | 
| 4 | DERIVED  | c   | ALL | idx_vid | NULL | NULL | NULL  | 616 | Using where; Using join buffer | 
| 5 | DERIVED  | a   | ALL | vid  | NULL | NULL | NULL  | 1015 | Using temporary; Using filesort | 
| 5 | DERIVED  | v   | ref | idx_vid | idx_vid | 32  | db.a.vid | 10 | Using index      | 
|NULL| UNION RESULT | <union1,3> | ALL | NULL  | NULL | NULL | NULL  | NULL |         | 
+----+--------------+------------+------+----------+---------+---------+----------+------+---------------------------------+ 
11 rows in set (0.02 sec) 

Как отредактировать этот оператор MySQL? Также есть хороший инструмент рефакторинга для оператора MySQL?

Спасибо.

+0

Что в этом плохого? Почему вы хотите реорганизовать? –

+0

Вы можете попробовать Toad для Mysql tool, это бесплатная программа. – rkosegi

+0

@SergioTulentsev: объясните результат прилагается. – user1045217

ответ

1

Это один, казалось, работал для меня:

select Channel as name,count(distinct a1.aid) as total_episode 
from channelListingItem c 
left join 
(
select a.aid, a.vid 
from videoItem v INNER JOIN aid2vid a USING(vid) 
) a1 on a1.aid = c.aid 
group by Channel; 

Из того, что я могу увидеть следующий запрос, который используется дважды в вложенное представление:

SELECT a.aid, a.vid 
FROM videoItem v INNER JOIN aid2vid a USING(vid) 
GROUP BY a.aid 

Is используется для получения отдельного списка значений aid и vid, которые существуют как в videoItem, так и в aid2vid. Я заменил GROUP BY во встроенном представлении с помощью COUNT(DISTINCT), чтобы добиться того же, так как вы не используете какие-либо агрегированные функции во встроенной части обзора запроса.

Я думаю, вам не нужно разделить запрос на две части, соединенные союзом, то есть частью 1, чтобы получить число эпизодов> 0 и часть 2, чтобы получить количество эпизодов = 0. Этого можно достичь в одном GROUP BY.

Надеюсь, это поможет!

+1

Это работает и для меня. Хотя тот, который ниже использует COALESCE, дает w/тот же результат, MySQL объясняет, похоже, пользуется этим ответом. Поэтому я выбираю этот. – user1045217

1

Я мог бы быть способом, но я считаю, что следовать за тем же результатом, что и ваш исходный запрос.

Суть его состоит в

  • Добавить total_episode поле для вашего LEFT JOIN.
  • Используйте COALESCE для возврата либо значения total_episode, либо 0.

SQL Заявление

SELECT c1.Channel as name 
     , COALESCE(total_episode, 0) 
FROM channelListingItem c1 
     LEFT JOIN ( 
      SELECT c.Channel 
        , count(*) as total_episode 
      FROM (
        SELECT a.aid 
          , a.vid 
        FROM videoItem v 
          INNER JOIN aid2vid a ON a.vid = v.vid 
        GROUP BY 
          a.aid 
        ) a1 
        INNER JOIN channelListingItem c ON c.aid = a1.aid 
      GROUP BY 
        c.Channel 
     ) c2 ON c2.Channel = c1.Channel 
    GROUP BY 
     name 
Смежные вопросы