我如何重构这个MySQL查询?

时间:2012-01-04 07:16:55

标签: 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
);

基本上,这句话的作用是在每个频道中获得正确的计数剧集。为后续表(videoItem)中的vid o vid分配零。

请注意

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语句也有很好的重构工具吗?

感谢。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

用于获取aidvid中存在的videoItemaid2vid值的明确列表。我已使用GROUP BY替换了内联视图中的COUNT(DISTINCT)以实现相同的功能,因为您未在查询的内联视图部分中使用任何聚合函数。

我认为您不需要将查询拆分为由联合加入的两个部分,即第1部分以获取剧集计数&gt; 0和第2部分得到剧集计数= 0.这可以在一个GROUP BY中实现。

希望这有帮助!