2010-08-12 64 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