2012-07-22 74 views
0

好的一點引物;我是一名PHP/JS/C開發專家,但從未完全掌握過MySQL。如果你能回答我的問題,那將是非常好的,但如果你能指點我的方向好的資源來了解複雜的MySQL查詢做什麼和不該做什麼(主要是從效率的角度來看),那將是非常有用的。在一個單一的表MySQL匹配來自同一表的列

目的

我需要找到相似性/相重疊,同時仍拉動整個結果集(以LEFT JOIN與實際標題/描述內容是在另一個表)。

表格非常簡單;它包含3列(page,user,time)。

基本上每個查詢將有兩個用戶。我需要拉匹配User 1所有結果的數量,匹配User 2所有結果的數量,併爲部分重疊的所有列(加上LEFT JOIN)(其中兩個User 1User 2在表中的匹配。

示例查詢

這個查詢很有用,但速度非常慢(運行起來需要幾分鐘的時間),而且由於子查詢的緣故,我猜這樣做效率低下,如果有任何SQL專家可以指出一個更有效的方法來做到這一點以及爲什麼)它將會很受歡迎。

SELECT DISTINCT `page`, 
    (SELECT COUNT(*) FROM `m_likes` WHERE `user` = "1") AS userLikes, 
    (SELECT COUNT(*) FROM `m_likes` WHERE `user` = "2") AS friendLikes 

    FROM `m_likes` LEFT JOIN `app_pages` AS page ON (page.id = `page`) 

     WHERE `page` IN (SELECT `page` FROM `m_likes` WHERE `user` = "1") 
     AND `page` IN (SELECT `page` FROM `m_likes` WHERE `user` = "2") 

     AND (`user` = "1" OR `user` = "2") 

EXPLAIN查詢結果

id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY  m_likes index NULL page 604 NULL 35043 Using where; Using index; Using temporary 
1 PRIMARY  page eq_ref PRIMARY PRIMARY 767 tablename.m_likes.page 1 
5 DEPENDENT SUBQUERY m_likes unique_subquery page page 604 func,const  1 Using index; Using where 
4 DEPENDENT SUBQUERY m_likes unique_subquery page page 604 func,const  1 Using index; Using where 
3 SUBQUERY m_likes index NULL page 604 NULL 35043 Using where; Using index 
2 SUBQUERY m_likes index NULL page 604 NULL 35043 Using where; Using index 

表結構

app_pagesid VARCHAR(255),name VARCHAR(255),category VARCHAR(255)

m_likespage VARCHAR(255),user VARCHAR(255),time INT(20)

m_likes.page = app_pages.id

另外值得注意的,不幸的是,用戶&頁ID必須是VARCHAR代替INT,因爲不存在的這保證在64位系統上運行,並且某些ID值大於32位系統允許的最大值......希望這不會增加主要性能。

輸出例

array (size=156) 
    0 => 
    array (size=6) 
     'page' => string '100861973286778' (length=15) 
     'time' => string '1297383617' (length=10) 
     'name' => string 'Leila' (length=5) 
     'category' => string 'Book' (length=4) 
     'userLikes' => string '104' (length=3) 
     'friendLikes' => string '52' (length=2) 
    1 => 
    array (size=6) 
     'page' => string '10150160788195604' (length=17) 
     'time' => string '1272653871' (length=10) 
     'name' => string 'Frisbee Golfing' (length=15) 
     'category' => string 'Interest' (length=8) 
     'userLikes' => string '104' (length=3) 
     'friendLikes' => string '52' (length=2) 
+1

使用[EXPLAIN](http://dev.mysql.com/doc/refman/5.5/en/explain.html)可以更好地理解MySQL如何執行您的查詢 – Jocelyn 2012-07-22 23:27:14

+0

我已經嘗試使用EXPLAIN,但坦率地說它不是這很有用;查詢完全按照我的預期執行,但它並沒有給我任何關於如何更好地設計它的見解,這正是我希望SQL專家能夠做到的。 – Julian 2012-07-22 23:42:51

+0

你可以在這裏發佈結果嗎? – blockhead 2012-07-23 00:01:04

回答

1

爲什麼你的查詢運行這麼慢,是因爲你正在執行FOUR獨立的子查詢,實際上最終的EACH行執行的原因。

相反,你可以做一個子查詢的笛卡爾乘積得到計數(只執行一次):

SELECT a.page, c.userLikes, c.friendLikes 
FROM m_likes a 
INNER JOIN app_pages b ON a.page = b.id 
CROSS JOIN 
(
    SELECT 
     COUNT(CASE WHEN user = '1' THEN 1 END) AS userLikes, 
     COUNT(CASE WHEN user = '2' THEN 1 END) AS friendLikes 
    FROM m_likes 
    WHERE user IN ('1','2') 
) c 
WHERE a.user IN ('1','2') 
GROUP BY a.page 
HAVING COUNT(1) = 2 

這個查詢會檢索所有的網頁用戶1和2都喜歡,沿與他們的喜歡總數(這將在結果集中重複)。

+0

嘗試了這個查詢,但它似乎沒有與HAVING COUNT(1)= 2一起工作...我拿出那部分來測試其餘部分,它看起來很好,但它選擇了整個結果集(我猜測HAVING語句是實際分解子集的部分)。任何想法可能會在那裏?在查看HAVING命令後,似乎我只需要找出由CASE創建的臨時列的別名(它似乎不是'1') – Julian 2012-07-23 01:09:45

+0

@Julian,你能解釋一下實際存在的錯誤嗎?當你放入'HAVING'子句時的結果集?它會產生錯誤嗎?這裏的'HAVING'子句基本上選擇用戶'1'和'2'都喜歡的所有頁面。這是假定頁面 - >用戶的字段的組合是唯一的(用戶不能多次喜歡頁面)。 – 2012-07-23 01:14:20

+0

@Julian另外,在這一點上,如果您發佈了來自兩個表格的一些示例數據以及所需的輸出,那將非常有幫助。 – 2012-07-23 01:14:47

相關問題