2016-05-19 9 views
0

このselectステートメントを使用して、異なるテーブルから情報を分離し、同じ構造を維持し、最後に結果をグループ化しますが、 "fi"テーブルには何千もの行があるため、結果を処理するのに時間がかかります。より高速な結果を得るために、以下のクエリを最適化する方法はありますか?データ型varchar型のft.fdataはSelectステートメントが処理に時間がかかります

select Referencia,Designacao,cor,Tamanho,sum(qtd),entreguesede,stock 
from 
(
Select 
isnull(ST.REF,'') as Referencia 
, fi.design as Designacao 
, fi.cor Cor 
, fi.tam Tamanho 
, sum(case when ft.tipodoc=3 then -fi.qtt else fi.qtt end) as Qtd 
, isnull((select sum(case when sl.cm=1 then sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) EntregueSede 
, isnull((select sum(case when sl.cm<50 then sl.qtt when sl.cm>50 then -sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) Stock 

from fi (nolock) 
inner join ft (nolock) on ft.ftstamp=fi.ftstamp 
inner join td (nolock) on ft.ndoc=td.ndoc and td.regrd=0 
left join st (nolock) on fi.ref = st.ref or fi.oref = st.ref 
left join sz (nolock) on sz.no = fi.armazem 

where fi.composto=0 
and ft.fdata between '20160301' and '20160331' 
and ft.anulado=0 
and ft.fno>=0 
and fi.qtt<>0 
and ft.tipodoc in(1, 2, 3) 
and ((FI.ARMAZEM between 1000 and 1999) or fi.armazem in(10,20)) 
and isnull(sz.nome,'') like '%' + + '%' 

group by FI.REF, fi.design,fi.cor,fi.tam,st.ref 

union all 

Select 
isnull(ST.REF,'') Referencia 
, fi.design Designacao 
, fi.cor Cor 
, fi.tam Tamanho 
,sum(case when ft.tipodoc=3 then -fi.qtt else fi.qtt end) as Qtd 
, isnull((select sum(case when sl.cm=1 then sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) EntregueSede 
, isnull((select sum(case when sl.cm<50 then sl.qtt when sl.cm>50 then -sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) Stock 

from fi (nolock) 
inner join ft (nolock) on ft.ftstamp=fi.ftstamp 
inner join td (nolock) on ft.ndoc=td.ndoc and td.regrd=0 
left join st (nolock) on fi.ref = st.ref or fi.oref = st.ref 
left join sz (nolock) on sz.no = fi.armazem 
where fi.composto=0 
and ft.fdata >= '20150505' 
and ft.fdata between '20160301' and '20160331' 
and ft.anulado=0 
and ft.fno>=0 
and fi.qtt<>0 
and ft.ndoc in (401,501) 
and isnull(sz.nome,'') like '%' + + '%' 

group by FI.REF, fi.design, fi.cor, fi.tam, st.ref 

union all 

select 
isnull(ST.REF,'') Referencia 
, bi.design as Designacao 
, bi.cor Cor 
, bi.tam Tamanho 
,sum(bi.qtt) as Qtd 
, isnull((select sum(case when sl.cm=1 then sl.qtt else 0 end) from sl (nolock) where sl.ref=bi.ref and sl.cor=bi.cor and sl.tam=bi.tam and sl.datalc<='20160331'),0) EntregueSede 
, isnull((select sum(case when sl.cm<50 then sl.qtt when sl.cm>50 then -sl.qtt else 0 end) from sl (nolock) where sl.ref=bi.ref and sl.cor=bi.cor and sl.tam=bi.tam and sl.datalc<='20160331'),0) Stock 

from bi(nolock) 
inner join bo(nolock) on bo.bostamp = bi.bostamp 
inner join bo2(nolock) on bo2stamp = bo.bostamp 
inner join ts(nolock) on ts.ndos = bo.ndos and ts.ndos = 60 
left join st(nolock) on bi.ref = st.ref 
left join sz(nolock) on sz.no = bi.armazem 
where bi.composto=0 
and bo.dataobra between '20160301' and '20160331' 
and bo2.anulado= 0 
and bo.obrano >= 0 
and bi.qtt<>0 
and isnull(sz.nome,'') like '%' + + '%' 

group by bi.REF, bi.design, bi.cor, bi.tam, st.ref 
) a 
group by Referencia,Designacao,cor,Tamanho,entreguesede,stock 
order by 1,2,3,4,6,7 
+1

あなたが実行計画のXMLを取得する方法を知っていますか?もしそうなら、投稿してください。そうでない場合は、次のURLを参照してください。https://msdn.microsoft.com/en-us/library/ms190646.aspx –

+1

何千もの行で問題は発生しません。適切なインデックスがあることを確認しましたか?あなたがSQLサーバを使用している場合は、クエリアナライザを見てください。 – DoctorMick

+0

「20160301」と「20160331」の間の「ft.fdata」は、その月のすべてではないことにご注意ください。 – shadow

答えて

0

1) ですか?それは数ある場合は、代わりに

and ft.fdata between '20160301' and '20160331' 

2の

and ft.fdata between 20160301 and 20160331 

を使用) これを使用することは何ですか?それは私には意味がありません。

and isnull(sz.nome,'') like '%' + + '%' 

3)未パフォーマンスに関連するが、私は列に)サブ選択(下のコードの例)ColumnNumberに

order by 1,2,3,4,6,7 
BY

4をORDERを使用しないように、あなたをお勧めしますが、通常は実際にありますパフォーマンスに関する悪い考え。可能であれば、サブクエリとして使用してください。時には、クエリ「労働組合のすべて」や「労働組合」と組み合わせる

isnull((select sum(case when sl.cm=1 then sl.qtt else 0 end) from sl (nolock) where sl.ref=bi.ref and sl.cor=bi.cor and sl.tam=bi.tam and sl.datalc<='20160331'),0) EntregueSede 

5)すでに他の人が推奨されているように(あなたのインデックスを確認してください)

6)は、私の経験から台無し実行計画()する傾向があります。しばしば、それぞれのクエリを一時テーブルにロードしてから一時テーブルを結合すると便利です。試してみるのに時間がかかりませんので多分あなたを助けます。

編集:ここでは

ポイント4のための例:ここでは

Select 
isnull(ST.REF,'') as Referencia 
, fi.design as Designacao 
, fi.cor Cor 
, fi.tam Tamanho 
, sum(case when ft.tipodoc=3 then -fi.qtt else fi.qtt end) as Qtd 
, isnull(EntregueSedeData.EntregueSedeSum ,0) EntregueSede -- <----- USE HERE THE SUM 
, isnull((select sum(case when sl.cm<50 then sl.qtt when sl.cm>50 then -sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) Stock 
from fi (nolock) 
inner join -- <----- JOIN YOUR DATA WITH CALCULATED SUM 
(
    select fi.ref, 
    fi.cor, 
    fi.tam, 
    sum(
      case 
       when sl.cm = 1 then sl.qtt 
       else 0 
      end 
     ) 
    as EntregueSedeSum 
    from sl (nolock) 
    where sl.datalc <= '20160331' 
) EntregueSedeData 
on sl.ref=fi.ref 
and sl.cor=fi.cor 
and sl.tam=fi.tam 
inner join ft (nolock) on ft.ftstamp=fi.ftstamp 
inner join td (nolock) on ft.ndoc=td.ndoc and td.regrd=0 
left join st (nolock) on fi.ref = st.ref or fi.oref = st.ref 
left join sz (nolock) on sz.no = fi.armazem 
where fi.composto=0 
and ft.fdata between '20160301' and '20160331' 
and ft.anulado=0 
and ft.fno>=0 
and fi.qtt<>0 
and ft.tipodoc in(1, 2, 3) 
and ((FI.ARMAZEM between 1000 and 1999) or fi.armazem in(10,20)) 
and isnull(sz.nome,'') like '%' + + '%' 
group by FI.REF, fi.design,fi.cor,fi.tam,st.ref 

ポイント6例:

create table #P1 -- replace xxx by your data type and add NOT NULL where possible 
(
    Referencia xxx PRIMARY KEY NOT NULL, -- don't know your data model, if Referencia is unique, use it the primary key 
    Designacao xxx 
    Cor xxx, 
    Tamanho xxx, 
    EntregueSede xxx, 
    Stock xxx 
) 

insert into #P1 
(
    Referencia, 
    Designacao, 
    Cor, 
    Tamanho, 
    EntregueSede, 
    Stock 
) 
Select 
isnull(ST.REF,'') as Referencia 
, fi.design as Designacao 
, fi.cor Cor 
, fi.tam Tamanho 
, sum(case when ft.tipodoc=3 then -fi.qtt else fi.qtt end) as Qtd 
, isnull((select sum(case when sl.cm=1 then sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) EntregueSede 
, isnull((select sum(case when sl.cm<50 then sl.qtt when sl.cm>50 then -sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) Stock 
from fi (nolock) 
inner join ft (nolock) on ft.ftstamp=fi.ftstamp 
inner join td (nolock) on ft.ndoc=td.ndoc and td.regrd=0 
left join st (nolock) on fi.ref = st.ref or fi.oref = st.ref 
left join sz (nolock) on sz.no = fi.armazem 
where fi.composto=0 
and ft.fdata between '20160301' and '20160331' 
and ft.anulado=0 
and ft.fno>=0 
and fi.qtt<>0 
and ft.tipodoc in(1, 2, 3) 
and ((FI.ARMAZEM between 1000 and 1999) or fi.armazem in(10,20)) 
and isnull(sz.nome,'') like '%' + + '%' 
group by FI.REF, fi.design,fi.cor,fi.tam,st.ref 

create table #P2 -- replace xxx by your data type and add NOT NULL where possible 
(
    Referencia xxx PRIMARY KEY NOT NULL, -- don't know your data model, if Referencia is unique, use it the primary key 
    Designacao xxx 
    Cor xxx, 
    Tamanho xxx, 
    EntregueSede xxx, 
    Stock xxx 
) 

insert into #P2 
(
    Referencia, 
    Designacao, 
    Cor, 
    Tamanho, 
    EntregueSede, 
    Stock 
) 
Select 
isnull(ST.REF,'') Referencia 
, fi.design Designacao 
, fi.cor Cor 
, fi.tam Tamanho 
,sum(case when ft.tipodoc=3 then -fi.qtt else fi.qtt end) as Qtd 
, isnull((select sum(case when sl.cm=1 then sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) EntregueSede 
, isnull((select sum(case when sl.cm<50 then sl.qtt when sl.cm>50 then -sl.qtt else 0 end) from sl (nolock) where sl.ref=fi.ref and sl.cor=fi.cor and sl.tam=fi.tam and sl.datalc<='20160331'),0) Stock 
from fi (nolock) 
inner join ft (nolock) on ft.ftstamp=fi.ftstamp 
inner join td (nolock) on ft.ndoc=td.ndoc and td.regrd=0 
left join st (nolock) on fi.ref = st.ref or fi.oref = st.ref 
left join sz (nolock) on sz.no = fi.armazem 
where fi.composto=0 
and ft.fdata >= '20150505' 
and ft.fdata between '20160301' and '20160331' 
and ft.anulado=0 
and ft.fno>=0 
and fi.qtt<>0 
and ft.ndoc in (401,501) 
and isnull(sz.nome,'') like '%' + + '%' 
group by FI.REF, fi.design, fi.cor, fi.tam, st.ref 

create table #P3 -- replace xxx by your data type and add NOT NULL where possible 
(
    Referencia xxx PRIMARY KEY NOT NULL, -- don't know your data model, if Referencia is unique, use it the primary key 
    Designacao xxx 
    Cor xxx, 
    Tamanho xxx, 
    EntregueSede xxx, 
    Stock xxx 
) 

insert into #P3 
(
    Referencia, 
    Designacao, 
    Cor, 
    Tamanho, 
    EntregueSede, 
    Stock 
) 
select 
isnull(ST.REF,'') Referencia 
, bi.design as Designacao 
, bi.cor Cor 
, bi.tam Tamanho 
,sum(bi.qtt) as Qtd 
, isnull((select sum(case when sl.cm=1 then sl.qtt else 0 end) from sl (nolock) where sl.ref=bi.ref and sl.cor=bi.cor and sl.tam=bi.tam and sl.datalc<='20160331'),0) EntregueSede 
, isnull((select sum(case when sl.cm<50 then sl.qtt when sl.cm>50 then -sl.qtt else 0 end) from sl (nolock) where sl.ref=bi.ref and sl.cor=bi.cor and sl.tam=bi.tam and sl.datalc<='20160331'),0) Stock 

from bi(nolock) 
inner join bo(nolock) on bo.bostamp = bi.bostamp 
inner join bo2(nolock) on bo2stamp = bo.bostamp 
inner join ts(nolock) on ts.ndos = bo.ndos and ts.ndos = 60 
left join st(nolock) on bi.ref = st.ref 
left join sz(nolock) on sz.no = bi.armazem 
where bi.composto=0 
and bo.dataobra between '20160301' and '20160331' 
and bo2.anulado= 0 
and bo.obrano >= 0 
and bi.qtt<>0 
and isnull(sz.nome,'') like '%' + + '%' 
group by bi.REF, bi.design, bi.cor, bi.tam, st.ref 

select Referencia, 
Designacao, 
cor, 
Tamanho, 
sum(qtd), 
entreguesede, 
stock 
from 
(
    select 
    Referencia, 
    Designacao, 
    Cor, 
    Tamanho, 
    EntregueSede, 
    Stock 
    from #P1 
    union all 
    select 
    Referencia, 
    Designacao, 
    Cor, 
    Tamanho, 
    EntregueSede, 
    Stock 
    from #P2 
    union all 
    select 
    Referencia, 
    Designacao, 
    Cor, 
    Tamanho, 
    EntregueSede, 
    Stock 
    from #P3 
) a 
group by Referencia, 
Designacao, 
cor, 
Tamanho, 
entreguesede, 
stock 
order by 1,2,3,4,6,7 
+0

ft.fdataは日付タイプフィールド –

+0

ft.fdataは日付タイプフィールドです。 '%+ @insert_variable_here +'% 'のように、isnull(sz.nome、' ')は'%+ + '%'のようになり、isnull(sz.nome、 '')となります。その名前で倉庫。私は別の目的のために私が使用する別のものからこのクエリを適応させた。私が望んでいるコンテンツを取得するための他の基準を使用しているので、これはあまり有用ではないと思われるので、それを破棄してください。 ColumnNumberによる注文については、パフォーマンスに関する問題はありますか? あなたのポイントは4、サブ選択については、私は同じ結果を得るために私のクエリに基づいて例を与えることができますが、サブクエリを使用して? –

+0

清算していただきありがとうございます。 isnull(sz.nome、 '')like '%+ +'% '変数isnull(sz.nome、' ')=' 'がなければ、isnullよりはるかに優れたパフォーマンスを達成していたので、 sz.nome、 '') '%+ +'% 'のようなものです。ポイント3(ORDER BY)に関しては、私が知っている限り、すでに述べたように、パフォーマンスには関係ありませんので、パフォーマンスだけを気にしていれば無視できます。ただし、注文が実際に必要ない場合は、パフォーマンスに関連します。 ORDER BYから特定の列を削除できる場合は、パフォーマンスに正の影響を与えます。 – Reboon

関連する問題