如何重构这个MySQL代码?

时间:2010-04-20 19:33:27

标签: mysql refactoring

    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

出于可读性和性能原因,我认为这段代码可以重构。但是如何?

EDITIONS

  1. 删除了外部选择

  2. 使第一个选择返回一个总和而第二个选择返回另一个值

  3. SUM替换为AVG

4 个答案:

答案 0 :(得分: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子句,并没有添加任何内容,因此我删除了它。与LEFT OUTER JOIN方法相比,NOT IN效率低,所以我替换了它。使用UNION可以很容易地将两个>=组合成一个。

<强>更新 请注意使用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  

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

答案 2 :(得分: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获取这些值的整个行。

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

同样*被认为是有害的。如果要使查询向前兼容以后可能对数据库模型进行更改,请按名称指定列。