2010-08-12 52 views
0

使用MySQLSQL:基於聚合函數的過濾組

所以我試圖改進我寫的查詢。我目前的查詢工作,但我覺得我可以更有效率

本質上,我有一個表,列出誰與誰談話,以及多少。

的記錄是這樣的:

電子郵件名稱狀態數prod_ref (我會發布在帖子的末尾用示例輸出的表率) PK =電子郵件,姓名等 名稱是一封內部郵件針對運行此組織的地址。 (IE sue @ innatech只是起訴)

我最初想要的是一個查詢,它將返回每個電子郵件地址的計數最高的記錄。

我能想出這裏最好的是:

SELECT email, name 
FROM email_tbl AS a INNER JOIN 
    (SELECT email, MAX(count) cnt 
     FROM email_tbl 
     GROUP BY email) AS b ON a.email = b.email AND a.count = r.cnt 

這似乎相當優化。然後,我可以通過向子查詢添加一個HAVING子句來進一步過濾我的結果,以指定諸如SUM(count)> 20等的東西。

令人討厭的部分是狀態欄。 (我知道,有一些數據複製問題會破壞正確的ER樣式,但由於某些原因,我只允許使用一個表格)。

狀態字段描述了是否應該忽略特定的電子郵件。從理論上講,電子郵件的所有記錄應該有相同的字段,但我想說明這是不正確的情況。基本上,如果存在狀態爲'忽略'的記錄,我想扔掉該記錄上的電子郵件。

我能想到這樣做,這是另一個子查詢,通過增加月底

WHERE a.email NOT IN 
    (SELECT DISTINCT email 
    FROM email_tbl 
    WHERE status = 'ignore') 

它工作的唯一方式......但筆者在市場上我總是提高我的工具,所以我想知道是否有更好的方法來實現這一點。

附錄A示例設置

email_tbl 

[email protected];phil;good;12 
[email protected];sue;good;5 
----------------------- 
[email protected];phil;good;2 
[email protected];sue;good;2 
[email protected];fred;good;8 
----------------------- 
[email protected];phil;good;5 
[email protected];sue;ignore;4 

將返回

[email protected];phil 
[email protected];fred 

回答

1

只是一對夫婦即興查詢的,所以你必須要測試性能:

使用NOT EXISTS而不是IN應該至少比你所擁有的更快,因爲它一找到匹配就可以停止處理子查詢。它是相關的,所以你必須測試。

SELECT 
    email, 
    name 
FROM 
    Email_Tbl AS T1 
INNER JOIN 
(
    SELECT email, MAX(count) cnt 
    FROM email_tbl 
    GROUP BY email 
) AS SQ ON 
    SQ.email = T1.email AND 
    SQ.cnt = T1.count 
WHERE 
    NOT EXISTS 
    (
     SELECT * 
     FROM Email_Tbl T2 
     WHERE T2.email = T1.email 
      AND T2.status = 'Ignore' 
    ) 

SELECT 
    email, 
    name 
FROM 
    Email_Tbl T1 
LEFT OUTER JOIN Email_Tbl T2 ON 
    T2.email = T1.email AND 
    (
     T2.count > T1.count OR 
     T2.status = 'Ignore' 
    ) 
WHERE 
    T2.email IS NULL 

SELECT 
    email, 
    name 
FROM 
    Email_Tbl T1 
LEFT OUTER JOIN Email_Tbl T2 ON 
    T2.email = T1.email AND 
    T2.count > T1.count 
LEFT OUTER JOIN Email_Tbl T3 ON 
    T3.email = T1.email AND 
    T3.status = 'Ignore' 
WHERE 
    T2.email IS NULL OR 
    T3.email IS NULL