2012-01-04 30 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 
); 

基本上,這種說法確實是讓每個通道正確的計數插曲&爲渠道W/O 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

它有什麼問題?你爲什麼要重構? – 2012-01-04 07:18:18

+0

你可以嘗試Toad for Mysql工具,它是免費的。 – rkosegi 2012-01-04 07:18:26

+0

@SergioTulentsev:解釋附加的結果。 – user1045217 2012-01-04 08:09:24

回答

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 

是用於獲取存在於videoItemaid2vid中的aidvid值的明確列表。我將內聯視圖中的GROUP BY替換爲COUNT(DISTINCT)以實現同樣的效果,因爲您沒有在查詢的內聯視圖部分使用任何聚合函數。

我認爲你不需要將查詢拆分成由一個聯合連接起來的兩部分,即第1部分使情節數> 0,第2部分使情節數= 0。這可以在一個GROUP BY中實現。

希望這會有所幫助!

+1

這對我也適用。雖然下面使用COALESCE的結果會產生相同的結果,但MySQL解釋似乎對此答案有利。所以我選擇了這一個。 – user1045217 2012-01-04 09:14:06

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