如何重构这个MySQL查询?
我有以下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
(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
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解释似乎更倾向于这个答案。所以我选择了这个。