2016-07-27 45 views
0

我試圖找出如何加快查詢使用連接和分組來獲取表中的行作爲另一列中的列表並且也使用having子句。優化一個MySQL查詢,從另一個表中選擇行作爲列,並使用HAVING子句

我有以下兩個表:

用戶:

id name 
1 bob 
2 joe 
3 paul 

財產:

id user_id type_id type  name 
1 1  1  car   honda 
2 1  2  computer mac 
3 2  1  car   toyota 
4 2  2  computer pc 
5 2  3  phone  htc 
6 3  1  car   toyota 
7 3  2  computer pc 
8 3  3  phone  samsung 

我使用下面的查詢:

select 
    p.user_id, 
    u.name, 
    max(case when p.type=1 then p.name end) as car, 
    max(case when p.type=2 then p.name end) as computer, 
    max(case when p.type=3 then p.name end) as phone 
from 
    possesions p inner join users u 
    on p.user_id=u.id 
group by 
    p.user_id, 
    u.name 
having 
    car='toyota' 

得到這作爲輸出:

user_id name car  computer phone 
2  joe  toyota pc   htc 
3  paul toyota pc   samsung 

有一個相當數量的數據 - 約75k用戶,200k possesions和25不同擁有類型。查詢花費約5秒鐘。當我做一個解釋的查詢我得到這個:

id select_type table  type possible_keys   key     key_len ref    rows  Extra 
1 SIMPLE  users  index (NULL)     PRIMARY    4   (NULL)   77453 Using index 
1 SIMPLE  possesions ref FK_possessions_users FK_possessions_users 4   mydb.users.id 1  

我有所有的id列索引。只是想知道是否還有其他事情可以做,以加快速度。如果我刪除了HAVING子句,它當然會變得很快。任何幫助將不勝感激,謝謝。

回答

0

這是您的查詢:

select u.id, u.name, 
     max(case when p.type = 1 then p.name end) as car, 
     max(case when p.type = 2 then p.name end) as computer, 
     max(case when p.type = 3 then p.name end) as phone 
from users u join 
    possesions p 
    on p.user_id = u.id 
group by u.id, u.name 
having car = 'toyota'; 

MySQL提供了基本的優化聚集查詢沒有機會。您可以將其更改爲join版本以查看是否有效。因此,假設每種類型最多出現一次:

select u.id, u.name, pc.name as car, pcomp.name as computer, pp.name as phone 
from users u join 
    possesions pc 
    on pc.user_id = u.id and 
     pc.type = 1 and pc.name = 'toyota' left join 
    possessions pcomp 
    on pcomp.user_id = u.id and pcomp.type = 2 left join 
    possessions pp 
    on pp.user_id = u.id and pp.type = 3; 

對於這一點,你要對pc(user_id, type, name)的索引。

注意:查詢的節省是通過避免與group by的聚合。如果給定類型有多個名稱,則可能需要進行聚合。

相關問題