我正在尝试改进此查询。它来自一个更大的桌子,但我已经采取了必需品,并将其削减到下面的问题。此表为我们提供了特定月份,商店和产品组的销售额。对于每一行(即月/商店/产品组合),我需要在此之前的前两个和四个月的销售总额。
我所提供的内容在提供正确的值方面效果很好,但它在大型桌面上是一种性能损失。我查看了具有PRECEDING / FOLLOWING约束的OVER子句,但我使用的SQL Server 2008不支持这些。您是否看到了更优化的方法来重写它并给出相同的期望结果?谢谢。
create table #sales_by_month
(
period int, --YYYYMM
store varchar(8), --store number
product_group varchar(8),
sales int
)
insert into #sales_by_month values (201701, 51, 'shoes', 12)
insert into #sales_by_month values (201701, 51, 'clothes', 15)
insert into #sales_by_month values (201701, 12, 'shoes', 10)
insert into #sales_by_month values (201701, 12, 'clothes', 9)
insert into #sales_by_month values (201702, 51, 'shoes', 0)
insert into #sales_by_month values (201702, 51, 'clothes', 20)
insert into #sales_by_month values (201702, 12, 'shoes', 30)
insert into #sales_by_month values (201702, 12, 'clothes', 8)
insert into #sales_by_month values (201703, 51, 'shoes', 7)
insert into #sales_by_month values (201703, 51, 'clothes', 4)
insert into #sales_by_month values (201703, 12, 'shoes', 21)
insert into #sales_by_month values (201703, 12, 'clothes', 0)
insert into #sales_by_month values (201704, 51, 'shoes', 50)
insert into #sales_by_month values (201704, 51, 'clothes', 4)
insert into #sales_by_month values (201704, 12, 'shoes', 16)
insert into #sales_by_month values (201704, 12, 'clothes', 20)
insert into #sales_by_month values (201705, 51, 'shoes', 21)
insert into #sales_by_month values (201705, 51, 'clothes', 17)
insert into #sales_by_month values (201705, 12, 'shoes', 0)
insert into #sales_by_month values (201705, 12, 'clothes', 5)
select
period,
store,
product_group,
(select sum(sales)
from #sales_by_month x2
where x2.store = #sales_by_month.store
and x2.product_group = #sales_by_month.product_group
and left(x2.period, 4) * 12 + right(x2.period, 2)
between left(#sales_by_month.period, 4) * 12 + right(#sales_by_month.period, 2) - 1
and left(#sales_by_month.period, 4) * 12 + right(#sales_by_month.period, 2) ) sales_to_date_last_2_months,
(select sum(sales)
from #sales_by_month x4
where x4.store = #sales_by_month.store
and x4.product_group = #sales_by_month.product_group
and left(x4.period, 4) * 12 + right(x4.period, 2)
between left(#sales_by_month.period, 4) * 12 + right(#sales_by_month.period, 2) - 3
and left(#sales_by_month.period, 4) * 12 + right(#sales_by_month.period, 2)) sales_to_date_last_4_months
from
#sales_by_month
--drop table #sales_by_month
答案 0 :(得分:1)
您可以在SQL Server 2012中使用带有sum()
的窗口子句。假设您拥有每个月的数据并存储
select sbm.*,
sum(sales) over (partition by store, productgroup
order by period
rows between 4 preceding and 2 preceding
) as sales_2_4
from #sales_by_month sbm;
这在SQL Server 2008中不起作用。我建议apply
:
with sbm as (
select sbm.*,
row_number() over (partition by store, productgroup order by period) as seqnum
from #sales_by_month sbm
)
select sbm.*, sbm2.sales_2_4
from sbm outer apply
(select sum(sbm2.sales) as sales_2_4
from sbm sbm2
where sbm2.store = sbm.store and sbm2.productgroup = sbm2.productgroup and
sbm2.seqnum between sbm.seqnum - 4 and sbm.seqnum - 2
) sbm2
答案 1 :(得分:0)
试试这个:
SELECT CONVERT(DATE,SUBSTRING(CONVERT(NVARCHAR,period),1,4) +'-'+ SUBSTRING(CONVERT(NVARCHAR,period),5,2) + N'-01')periodDt
,DATEADD(MONTH,2,CONVERT(DATE,SUBSTRING(CONVERT(NVARCHAR,period),1,4) +'-'+ SUBSTRING(CONVERT(NVARCHAR,period),5,2) + N'-01'))periodDt2
,DATEADD(MONTH,4,CONVERT(DATE,SUBSTRING(CONVERT(NVARCHAR,period),1,4) +'-'+ SUBSTRING(CONVERT(NVARCHAR,period),5,2) + N'-01'))periodDt4
,* INTO #t1 FROM #sales_by_month
SELECT periodDt,periodDt2,periodDt4,period,store,product_group, SUM(sales)sales INTO #t2 FROM #t1 GROUP BY periodDt,periodDt2,periodDt4,period,store,product_group
SELECT ISNULL([2m].store,[4m].store),ISNULL([2m].product_group,[4m].product_group),ISNULL(sales2month,0),ISNULL(sales4month,0) FROM
(SELECT store,product_group,sales sales2month FROM #t2 WHERE perioddt2 >= GETDATE())[2m]
FULL JOIN
(SELECT store,product_group,sales sales4month FROM #t2 WHERE perioddt4 >= GETDATE())[4m]
ON [2m].store = [4m].store AND [2m].product_group = [4m].product_group