有效地使用SQL GROUP BY、SUM、COUNT
我的产品销售表如下所示:有效地使用SQL GROUP BY、SUM、COUNT,sql,performance,count,group-by,sum,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 product | total | ptype
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
product | total | ptype | pdate
p1 | 3.00 | VAR | (NULL)
p2 | 1.50 | sale | 02/03
p3 | 5.25 | base | 10/10
我想建立一个表格,每行显示一个产品,金额的总和,如果产品是唯一的,显示类型else,显示类型为“VAR”,如果产品是唯一的,显示日期else,显示日期为NULL。结果如下所示:
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
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
但我想知道是否有一种更有效的方法可以达到同样的效果 试试这段代码:
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;
希望它能工作。不需要使用任何形式的子查询或内联视图。根据数据库引擎的复杂程度,这些构造可能会对性能产生负面影响 这是您所要求的,即使在最原始的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都不是null
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
如果您针对任何主要数据库(如SQL Server)运行此操作,查询优化器可能会代表您处理大部分优化。也就是说,您可以很容易地使用具有单个GROUPBY的内部查询来实现这一点。下面是一个可以使用的示例:
此SQL将不会在SQL Server上运行;不确定其他数据库引擎。在Sybase中,这给了我一个错误,即“ptype”和“pdate”也必须出现在GROUP BY中。哇,我被当场抓住。完全忘记了要执行分组函数,实际上需要对表进行分组;我做了同样的观察,它可能不是你真正想要的。我将投票赞成这个答案