如何重构这个MySQL查询?

如何重构这个MySQL查询?,mysql,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 ) UN

我有以下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的通道分配零

注意

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)
+----+--------------+------------+------+----------+---------+---------+----------+------+---------------------------------+
|id |选择|类型|表格|类型|位置|键|键|列|参考|行|额外|
+----+--------------+------------+------+----------+---------+---------+----------+------+---------------------------------+
|1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 313 |使用临时命令;使用文件排序|
|1 | PRIMARY | c | ALL | idx|u vid | NULL | NULL | NULL | 616 |使用where;使用连接缓冲区|
|2 |派生| a | ALL | vid | NULL | NULL | NULL | 1015 |使用临时;使用文件排序|
|2 |导出| v | ref | idx | u vid | idx | u vid | 32 | db.a.vid | 10 |使用索引|
|3 | UNION | c1 | ALL | NULL | NULL | NULL | NULL | 616 |使用临时命令;使用文件排序|
|3 | UNION | | | ALL | NULL | NULL | NULL | NULL | 28 |使用where;不存在|
|4 |派生| |所有|空|空|空|空| 313 |使用临时数据;使用文件排序|
|4 |派生| c | ALL | idx | vid | NULL | NULL | NULL | 616 |使用where;使用连接缓冲区|
|5 |派生| a | ALL | vid | NULL | NULL | NULL | 1015 |使用临时;使用文件排序|
|5 |导出| v | ref | idx | u vid | idx | u vid | 32 | db.a.vid | 10 |使用索引|
|空|并集结果| |全部|空|空|空|空|空||
+----+--------------+------------+------+----------+---------+---------+----------+------+---------------------------------+
一组11行(0.02秒)
如何重构这个MySQL语句?MySQL语句也有好的重构工具吗


谢谢。

我可以这样做,但我相信下面提供的结果与您最初的查询相同

其要点是

  • total\u插曲
    字段添加到您的
    LEFT JOIN
  • 使用
    COALESCE
    返回
    total\u插曲
    值或
    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

这个似乎对我有用:

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
用于获取同时存在于
videoItem
aid2vid
中的
aid
vid
值的不同列表。我在内联视图中将
组替换为
计数(不同)
,以实现同样的效果,因为在查询的内联视图部分没有使用任何聚合函数

我认为您不需要将查询拆分为两个由并集连接的部分,即第1部分获得大于0的事件计数,第2部分获得=0的事件计数。这可以通过
在一个
组中实现


希望这有帮助

怎么了?为什么要重构?你可以试试Toad for Mysql工具,它是免费的。@SergioTulentsev:explain result attached.@rkosegi:刚刚试过Toad。虽然它没有帮助很多(也许我只是玩了5分钟),谢谢你的工具建议。这对我也很有用。虽然下面使用COALESCE的方法产生了相同的结果,但MySQL解释似乎更倾向于这个答案。所以我选择了这个。