我正在努力解决其中一个出色的问题.我想在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.对于每个queryParameter,我有select语句.例如下面
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
如您所知,case语句也应该出现在join,where和group by语句中.因为QueryParameter’CR’,divionId和ProdId将作为null传递.
我将使用下面的exec运行storedProc(QueryParameter,CompID,RegionId,ProdId,DivId)
EXEC getProductMetrics(‘CR’,23,39,”,”)// CR只需要CompID和RegionId
EXEC getProductMetrics('CD',23, '', '',100) // CD requires only CompID and DivId
等等..
你能帮助我获得这个优化的查询吗?
最佳答案 为了以简单易读的方式执行此操作,我将创建一些辅助逻辑变量,如@ByCompany,以检查是否应该按公司分组等等.然后我会解释输入并相应地设置这些变量,然后在SELECT,WHERE和GROUP BY(以及可能的ORDER BY)部分创建一个使用它们的语句.不过,我认为不需要在FROM部分使用它们.
下面是一些示例代码 – 对于TransactSQL中的任何错误 – 我暂时没有使用它. 😉
DECLARE @ByCompany BIT = 0;
DECLARE @ByRegion BIT = 0;
[..]
IF @QueryParameter LIKE ('%C%') @ByCompany = 1
IF @QueryParameter LIKE ('%R%') @ByRegion = 1
[..]
Select
m.Day as Date,
CASE @ByCompany WHEN 1 THEN c.CompanyName ELSE 'ALL' END as 'CompanyName',
CASE @ByRegion WHEN 1 THEN r.RegionName ELSE 'ALL' END as 'RegionName',
[..]
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
[..]
where m.Day='12-5-2015'
and (c.CompanyId = @company OR @ByCompany = 0)
and (r.Region = @region OR @ByRegion = 0)
[..]
group by
Day,
CASE @ByCompany WHEN 1 THEN c.CompanyName ELSE 'ALL' END,
CASE @ByRegion WHEN 1 THEN r.RegionName ELSE 'ALL' END,
[..]
这样做,我们有简单易读的查询,当我们想要添加另一列进行分组时,这将是可维护的,比如subregion.