【发布时间】:2016-08-25 05:11:38
【问题描述】:
我正在尝试解决其中一个绝妙的问题。我想用sql中的case来优化SQL存储过程。
ProductMetrics 表格如下。此表包含有关产品销售价格和数量以及产品公司、销售区域、产品名称、市场部门的数据。
表 ProductMetrics 包含 10000 多行
ProductMetrics
| Day | CompanyId | RegionId | ProdId | DivId | Quantity | Sale
我们还有其他参考表 -
Company(CompanyId, CompanyName),
Region(RegionId, RegionName),
Product(ProdId, ProductName),
Division(DivId, DivisionName)
用户可以使用以下查询从该表中获取可读的统计信息。
Select m.Day, c.CompanyName, r.RegionName, p.ProductName, d.DivisionName, m.Quantity, m.Sale
from ProductMetrics m
left outer join Company on c.CompanyId = m.CompanyId
left outer join Region on r.RegionId = m.RegionId
left outer join Product on p.ProdId = m.ProdId
left outer join Division on d.DivId = m.DivId
where m.Day = '12-05-2015' and
m.CompanyId= 15 and
m.RegionId =10
我希望存储过程能够获得特定部门、产品或公司或两者的汇总统计数据。 SP 将根据我们传递的 queryParameter 返回。 getProductMetrics(queryParam, Day, CompanyId, RegionId, ProdId, DivId) QueryParameter 在以下示例中的括号中给出。
例如,
- (C) 获取特定公司的总数量和销售额。即按 CompanyId 分组
- (CR)按公司和地区分组的总数量和销售额。公司和地区的不同组合。
- (P) 按公司分组的总数量和销售额
- (D) 获取特定部门的总数量和销售额。
等等……
QueryParameter 可能是有价值的 - C, R, P, CRP, D, CR, CP, CD。对于每个查询参数,我都有选择语句。例如下面
IF @queryParameter IN ('C')
select m.Day, c.CompanyName, 'ALL' as Region, 'ALL' as ProductName, 'ALL' as DivisionName, SUM(m.Quantity), SUM(m.Sale)
from ProductMetrics m
left outer join Company on c.CompanyId = m.CompanyId
where m.Day = '12-05-2015' and
c.CompanyId =23
group by m.Day, c.CompanyName
等等.. 以上存储过程为我提供了所有可用部门、地区的特定产品和日期的总销售额。
对于存储过程,我需要编写 8 个带有 IF 条件的选择语句。
问题是而不是 8 个不同的 select 语句,我应该使用 CASE 语句来只有一个 storedProc 吗?
我在下面尝试过-
Select m.Day as Date,
CASE @QueryParameter
WHEN IN (C, CRP, CP, CR, CD) THEN c.CompanyName
ELSE 'ALL'
END as 'CompanyName',
CASE @QueryParameter
WHEN IN (R, CR) THEN r.RegionName
ELSE 'ALL'
END as 'RegionName',
CASE @QueryParameter
WHEN IN (P, CRP, CP) THEN p.ProductName
ELSE 'ALL'
END as 'ProductName',
CASE @QueryParameter
WHEN IN (D, CD) THEN d.DivisionName
ELSE 'ALL'
END as 'DivisionName',
SUM(Quantity), SUM(Sale)
from ProductMetrics m,
left outer join Company on c.CompanyId = m.CompanyId
left outer join Region on r.RegionId = m.RegionId
left outer join Product on p.ProdId = m.ProdId
left outer join Division on d.DivId = m.DivId
where m.Day='12-5-2015' and
r.Region = @region and
p.ProdId = @product
c.CompanyId = @company and
d.DivId = @division
group by Day, CompanyName,RegionName, ProductName, DivisionName
如您所知,join、where 和 group by 语句也应该存在 case 语句。因为对于 QueryParameter 'CR',divionId 和 ProdId 将作为 null 传递。
我将使用以下 exec 运行 storedProc(QueryParameter, CompID, RegionId, ProdId, DivId)
EXEC getProductMetrics('CR',23, 39, '','') // CR requires only CompID andRegionId
EXEC getProductMetrics('CD',23, '', '',100) // CD requires only CompID and DivId
等等.. 您能帮我获得这个优化的查询吗?
【问题讨论】:
-
MySQL 还是 SQL Server? (下定决心)
-
SQL Server ;) 非常感谢您的建议
-
你为什么坚持有一个select语句?我会使用 IF...ELSE 来评估哪些参数为 NULL,然后为它们生成单独的选择语句。查询优化器可能会更好地处理它们并且代码将更具可读性。
-
@PawełKucharski,看起来是个好主意 :)
-
这些是 case 表达式,而不是 case 语句。
标签: sql sql-server stored-procedures