私はこのクエリを改善しようとしています。それはずっと大きなテーブルから来たものですが、私は本質的なものを取り上げて、それを以下の問題に絞りました。この表は、月、店舗、製品グループの売上を示しています。各行(月/店舗/商品の組み合わせ)ごとに、その日までの過去2〜4ヶ月の売上の合計が必要です。このクエリを改善してください(過去の売上高の合計を1行ずつ)
正しい値を与えるという点で私が以下にしているのはうまく動作しますが、大きなテーブルではパフォーマンスが向上します。 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
私がここで見ている最大の問題は、サブクエリのすべての非SARGable述語です。このような関数で列をラップすると、インデックスを利用できないことを意味します。これが正しいデータ型を使用する理由です。日付のデータ型を持つ計算カラムを追加すると、ここで多くの状況に役立ちます。しかし、このクエリでは、これを少し簡単にすることができると思います。 –
@SeanLange - 期間に適切なデータ型を意味していますか?その後、BETWEEN句を動作させるために、すべての数式ではなく、元の日付計算関数(DATEADD()、DATEDIFF())を使用して作業しますか? – bvy
それはまさに私が言っていることです。そして、すべてのあなたの日付計算はGETDATEと保存された日付の値に対して行われます。 –