2010-08-12 5 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 ect.

Часть, которая делает ее противной, - это поле статуса. (Я знаю, есть некоторые проблемы дублирования данных, которые ломают правильный стиль ER, но по определенным причинам мне разрешена только одна таблица).

В поле статуса указано, следует ли игнорировать конкретное письмо. Теоретически все записи для электронной почты должны иметь одинаковые поля, но я хочу учитывать случай, когда это не так. В принципе, если существует запись со статусом «ignore», я хочу выбросить электронное письмо, которое находится на этой записи.

Единственный способ, которым я мог думать, чтобы сделать это был еще один суб-запрос, добавив к концу

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

Это работает ... но я всегда на рынке, чтобы улучшить свои инструменты, поэтому я хотите знать, есть ли лучший способ достичь этого.

Приложение А Пример установить

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 
Смежные вопросы