一尘不染

高效使用SQL GROUP BY,SUM,COUNT

sql

我有一张产品销售表,看起来可能如下:

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

但是我想知道是否有一种更有效的方法可以达到相同的结果。


阅读 156

收藏
2021-05-30

共1个答案

一尘不染

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

这就是您的要求,即使在最原始的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
2021-05-30