Select语句需要很长时间才能处理

时间:2016-05-19 08:17:14

标签: sql sql-server tsql

我使用这个select语句来收集来自不同表的信息,但是在它们之间保持相同的结构并最终对结果进行分组,但是因为" fi" table有数千行,处理结果需要很长时间。有没有办法优化下面的查询以获得更快的结果?

Milk
Work
Chair
...

1 个答案:

答案 0 :(得分:0)

1) 是数据类型varchar的ft.fdata吗?如果是数字,请使用

and ft.fdata between 20160301 and 20160331

而不是

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

2) 有什么用?这对我没有意义。

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

3)与性能无关,但我建议您不要使用ORDER BY ColumnNumber

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

4)在列中进行子选择(下面的代码示例)通常是关于性能的一个非常糟糕的主意。如果可能,尝试将其用作子查询。

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)有时候查询与“all all”或“union”相结合往往会破坏执行计划(根据我的经验)。如果首先将每个查询加载到临时表中然后组合临时表,通常会有所帮助。没有多少时间尝试它,所以它可以帮助你。

编辑:

这里是第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