SQL:根据聚合函数过滤组

时间:2010-08-12 16:23:45

标签: sql mysql optimization query-optimization

使用MySQL

所以我正在努力改进我写过的查询。我当前的查询有效,但我觉得我可以更有效率

基本上,我有一张表格列出了“谁与谁以及多少人谈论”。

记录如下:

电子邮件名称状态计数prod_ref (我将在帖子的末尾发布一个带有示例输出的示例集) PK =电子邮件和姓名 name是特定于运行此命令的组织的内部电子邮件地址。 (IE起诉@ 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

bob@bob.com;phil;good;12
bob@bob.com;sue;good;5
-----------------------
rob@bob.com;phil;good;2
rob@bob.com;sue;good;2
rob@bob.com;fred;good;8
-----------------------
dan@bob.com;phil;good;5
dan@bob.com;sue;ignore;4

将返回

bob@bob.com;phil
rob@bob.com;fred

1 个答案:

答案 0 :(得分: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