高效使用SQL GROUP BY,SUM,COUNT

时间:2012-06-29 04:07:03

标签: sql performance count group-by sum

我有一张产品销售表,可能如下所示:

product   | amount   | ptype    | pdate      
p1        | 1.00     | sale     | 01/01
p1        | 2.00     | base     | 01/02
p2        | 1.50     | sale     | 02/03
p3        | 5.25     | base     | 10/10

我希望构建一个表格,每行显示一个产品,金额总和,如果产品是唯一的,则显示其他类型显示类型为“VAR”,如果产品是唯一的则显示其他日期将日期显示为NULL。所以结果如下:

product   | total    | ptype    | pdate      
p1        | 3.00     | VAR      | (NULL)
p2        | 1.50     | sale     | 02/03
p3        | 5.25     | base     | 10/10

我通过以下方式完成了我需要的结果:

SELECT DISTINCT product
,(SELECT SUM(amount) FROM T as b GROUP BY b.product HAVING a.product = b.product ) as total
,(SELECT CASE WHEN COUNT(*) = 1 THEN a.ptype  ELSE 'VAR' END from T as b GROUP BY b.product HAVING a.product = b.product) as ptype
,(SELECT CASE WHEN COUNT(*) = 1 THEN a.pdate  ELSE NULL END from T as b GROUP BY b.product HAVING a.product = b.product) as pdate
FROM T as a

但我想知道是否有更有效的方法可以实现相同的结果。

3 个答案:

答案 0 :(得分:6)

无需使用任何形式的子查询或内联视图。根据数据库引擎的复杂程度,这些结构可能会对性能产生负面影响。

以下是您所要求的内容,即使是最原始的SQL引擎,它也应该可靠地对表进行单次扫描。

select product,
       sum(amount) as amount,
       case when count(*)=1 then min(ptype) else 'VAR' end as ptype,
       case when count(*)=1 then min(pdate) else null end as pdate
  from T
 group by product

以下内容并不完全符合您的要求,但我认为它可能更贴近您实际需要的内容。如果有多个不同的值组成聚合,它只会将ptype报告为VAR或pdate为NULL。

我添加了一个pcount列,这样你仍然可以识别单重聚合,即使ptype和pdate都不是nulll。

select product,
       sum(amount) as amount,
       count(*) as pcount,
       case when count(distinct ptype)=1 then min(ptype) else 'VAR' end as ptype,
       case when count(distinct pdate)=1 then min(pdate) else null end as pdate
  from T
 group by product

答案 1 :(得分:1)

如果您针对任何主要数据库(例如SQL Server)运行此操作,则查询优化器可能会代表您处理大部分优化。也就是说,您可以使用具有单个组的内部查询轻松地完成此操作。这是一个有效的例子,你可以玩:

http://sqlfiddle.com/#!3/f2e05/19/1

答案 2 :(得分:-1)

尝试这段代码:

SELECT DISTINCT product, x.total,
IF(COUNT(x.ptype) > 1, 'VAR', x.ptype) AS ptype,
IF(COUNT(x.pdate) > 1, NULL, x.pdate) AS pdate
FROM (SELECT DISTINCT product, SUM(amount) AS total, ptype, pdate FROM table GROUP BY product) AS x
JOIN table ON x.product = table.product
GROUP BY x.product;

希望它有效。