I have following MySQL query:
(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
);
Basically, what this statement does is to get the correct count episode in each channel & assign zero for channels w/o vid in consequent table (videoItem).
Note that
SELECT a.aid, a.vid
FROM videoItem v
INNER JOIN aid2vid a USING(vid)
GROUP BY a.aid
is duplicated twice and from explain this MySQL statement I don’t see MySQL re-use the query result.
+----+--------------+------------+------+----------+---------+---------+----------+------+---------------------------------+
| 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)
How do I refactor this MySQL statement? Also is there good refactor tool for MySQL statement?
Thanks.
This one seemed to work for me:
From what I can see the following query that you use twice in an inline view:
Is being used to get a distinct list of
aidandvidvalues that exist in bothvideoItemandaid2vid. I have replaced theGROUP BYin the inline view with aCOUNT(DISTINCT)to achieve the same thing since you are not using any aggregate functions in the inline view part of the query.I think you do not need to split the query into two parts joined by a union i.e. part 1 to get episode counts > 0 and part 2 to get episode counts = 0. This can be achieved in one
GROUP BY.Hope this helps!