2010-04-20 4 views
4
SELECT AVG(`col5`) 
    FROM `table1` 
    WHERE `id` NOT IN (
     SELECT `id` FROM `table2` 
     WHERE `col4` = 5 
    ) 
    group by `col2` having sum(`col3`) > 0 
UNION 
    SELECT MAX(`col5`) 
    FROM `table1` 
    WHERE `id` NOT IN (
     SELECT `id` FROM `table2` 
     WHERE `col4` = 5 
    ) 
    group by `col2` having sum(`col3`) = 0 

Для удобства чтения и производительности я думаю, что этот код можно было бы перестроить. Но как?Как реорганизовать этот код MySQL?

ИЗДАНИЯ

  1. удалена наружная выберите

  2. сделал первый выбор, чтобы вернуть сумму, а второй, чтобы вернуть другое значение

  3. заменил SUM от AVG

+0

Я смущен, потому что у вас есть «GROUP BY», но нет никаких столбцов в SELECT. Какие столбцы вы возвращаете? –

+0

@Marcus Я скорректировал пример, чтобы отразить реальную причину, по которой существует объединение –

+0

В любом случае вам не нужен UNION. Подумайте об использовании функции 'IF'. См. Мой ответ ниже обновленного. – codeholic

ответ

4
SELECT * 
FROM table1 t1 
left outer join table2 t2 on t1.id = t2.id and t2.col4 = 5 
where t2.id is null 
group by t1.col2 
having sum(col3) >= 0 

Внешний вид отсутствует FROM и ничего не добавляет, поэтому я удалил его. NOT IN неэффективен по сравнению с методом LEFT OUTER JOIN, поэтому я заменил его. Два UNION s были легко объединены в один, используя >=.

Update: Обратите внимание на использование UNION ALL, а не UNION. Я не думаю вы хотите удалить дубликаты, и он будет выполнять быстрее таким образом.

SELECT AVG(t1.col5) 
FROM table1 t1 
left outer join table2 t2 on t1.id = t2.id and t2.col4 = 5 
where t2.id is null 
group by t1.col2 
having sum(t1.col3) > 0 
UNION ALL 
SELECT MAX(t1.col5) 
FROM table1 t1 
left outer join table2 t2 on t1.id = t2.id and t2.col4 = 5 
where t2.id is null 
group by t1.col2 
having sum(t1.col3) = 0 
+0

Спасибо за ваши предложения: я удалил внешний выбор, я могу использовать предложение 'left external join', но я не могу объединить' UNION', потому что код немного отличается от того, что я написал вначале. Я переписал вопрос, чтобы показать, почему сложно совместить оба заявления. –

+0

Хорошо, никаких проблем. Я отправлю решение в одно мгновение. – RedFilter

+0

Вы правы, SUM и MAX плохо смешиваются. Реальные операции, которые я использую, - это AVG и MAX. Я отредактировал вопрос, чтобы отразить это. –

1
SELECT t1.* FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.id = t2.id 
WHERE t2.col4 <> 5 AND SUM(t1.col3) > 0 GROUP BY t1.col2 
+0

реальный код немного отличается от того, что я написал вначале. Я переписал вопрос, чтобы показать, почему сложно комбинировать оба утверждения. –

0

Я предполагаю, что вы хотите:

SELECT * FROM `table` 
WHERE col2 IN 
(SELECT col2 
    FROM `table1` 
    WHERE `id` NOT IN ( 
     SELECT `id` FROM `table2` 
     WHERE `col4` = 5 
    ) 
    group by `col2` having sum(`col3`) >= 0 
) 

При использовании GROUP BY, вы должны возвращать только столбцы, которые названы в пункте GROUP BY или которые включают в себя агрегатную функцию. Поэтому внутренний SELECT здесь получает значения col2, где сумма больше или равна нулю, тогда внешний SELECT захватывает всю строку для этих значений.

0
SELECT 
    IF(SUM(`table1`.`col3`) > 0, AVG(`table1`.`col5`), MAX(`table1`.`col5`)) 
FROM `table1` 
    LEFT JOIN `table2` ON `table2`.`id` = `table1`.`id` AND `table2`.`col4` = 5 
WHERE `table2`.`id` IS NULL 
GROUP BY `table1`.`col2` 
HAVING SUM(`table1`.`col3`) >= 0 

Также * считается вредным. Если вы хотите, чтобы ваш запрос был совместим с будущими изменениями в вашей модели БД, укажите столбцы по их именам.

+0

настоящий код немного отличается от того, что я написал вначале.Я переписал вопрос, чтобы показать, почему сложно совместить оба заявления –