2016-02-26 89 views
0

我有以下存储过程,在没有子查询的情况下运行时速度非常快。但是,我需要这些子选择的结果来获取我需要的信息。是否有另一种方法可以在不需要这些子查询的情况下获得这些结果,还是有任何方法可以使这些子查询更加优化?使用子查询更快地查询

USE [macal] 
GO 
/****** Object: StoredProcedure [dbo].[APsp_MapaClientesSemanaUmCliente] Script Date: 26/02/2016 10:56:53 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER Procedure [dbo].[APsp_MapaClientesSemanaUmCliente] 

@Vendedor varchar(20) = '', 
@NoCliente int = 0, 
@NoEstab int = 0 

AS 


DECLARE @DynamicPivotQuery AS NVARCHAR(MAX); 
DECLARE @ColumnName AS NVARCHAR(MAX); 

--Get distinct values of the PIVOT Column 
set @ColumnName = STUFF((
       select ISNULL(@ColumnName + ',','') 
       --+',' 
       + QUOTENAME(courses.anomes) 
       FROM (SELECT DISTINCT 'S'+ltrim(rtrim(str(ft.ftano)))+right('0'+ltrim(rtrim(str(datepart(week,ft.fdata)))),2) anomes,row_number() over (order by 'S'+ltrim(rtrim(str(ft.ftano)))+right('0'+ltrim(rtrim(str(datepart(week,ft.fdata)))),2)) row FROM ft where ft.fdata >= DATEADD(week,-11, GETDATE()) 
       group by 'S'+ltrim(rtrim(str(ft.ftano)))+right('0'+ltrim(rtrim(str(datepart(week,ft.fdata)))),2) 
       ) Courses 

       FOR XML PATH('') 
       ),1,1,''); 

     --  print @columnname 

DECLARE @ColumnNameSelect AS NVARCHAR(MAX) 

set @ColumnNameSelect = STUFF((
SELECT 
',ISNULL('+QUOTENAME(courses.anomes)+',0) AS '+QUOTENAME('S'+ltrim(rtrim(str(courses.row)))) 
FROM 
(
SELECT DISTINCT 'S'+ltrim(rtrim(str(ft.ftano)))+right('0'+ltrim(rtrim(str(datepart(week,ft.fdata)))),2) anomes,row_number() over (order by 'S'+ltrim(rtrim(str(ft.ftano)))+right('0'+ltrim(rtrim(str(datepart(week,ft.fdata)))),2)) row FROM ft where ft.fdata >= DATEADD(week,-11, GETDATE()) 
group by 'S'+ltrim(rtrim(str(ft.ftano)))+right('0'+ltrim(rtrim(str(datepart(week,ft.fdata)))),2) 
) Courses 
order by anomes 
FOR XML PATH('') 
),1,1,''); 

--print @columnnameselect 

--Prepare the PIVOT query using the dynamic 
SET @DynamicPivotQuery = 
N'SELECT 
nome, 
no, 
estab, 
morada, 
telefone, 
tlmvl, 
contacto, 
email, 
ZonaVenda, 
ZonaDist, 
segmento, 
classe, 
descpp, 
esaldo, 
plafondseg, 
pmr, 
ref, 
design, 
unidade, 
uni2, 
peso, 
u_uncx, 
PrecoTab, 
Desc1, 
Desc2, 
Desc4, 
Preco, 
DataPreco, 
media_semana, 

' + @ColumnNameSelect + ' 

FROM 
(
select cl.nome, 
ft.no, 
ft.estab, 
cl.morada, 
cl.telefone, 
cl.tlmvl, 
cl.contacto, 
cl.email, 
cl.zona ZonaVenda, 
cl.u_zonav ZonaDist, 
cl.segmento, 
cl.classe, 
cl.descpp, 
cl.esaldo, 
cl.U_EPLAFSEG plafondseg, 
ltrim(rtrim(str((select 
case 
when count(re.restamp) <> 0 then isnull(sum(datediff(dd,cc.datalc,re.procdata)),0)/count(re.restamp) else 0 end 
from rl (nolock) 
inner join re (nolock) on re.restamp = rl.restamp 
inner join cc (nolock) on cc.ccstamp = rl.ccstamp 
inner join cl (nolock) on cl.no = cc.no 
where cl.no=ft.no and cl.estab=ft.estab and 
re.process = 1 and 
re.procdata >= convert(char(8), dateadd(mm, -12, getdate()), 112) 
)))) PMR, 
fi.ref, 
st.design, 
st.unidade, 
st.uni2, 
st.peso, 
st.u_uncx, 
isnull((select top 1 fix.epv from fi(nolock) fix,ft(nolock) ftx where fix.ftstamp=ftx.ftstamp and fix.ref=fi.ref and fix.etiliquido>0 and ftx.no=ft.no and ftx.estab=ft.estab and ftx.tipodoc=1 order by ftx.fdata desc,ftx.fno desc),0) PrecoTab, 
isnull((select top 1 fix.desconto from fi(nolock) fix,ft(nolock) ftx where fix.ftstamp=ftx.ftstamp and fix.ref=fi.ref and fix.etiliquido>0 and ftx.no=ft.no and ftx.estab=ft.estab and ftx.tipodoc=1 order by ftx.fdata desc,ftx.fno desc),0) Desc1, 
isnull((select top 1 fix.desc2 from fi(nolock) fix,ft(nolock) ftx where fix.ftstamp=ftx.ftstamp and fix.ref=fi.ref and fix.etiliquido>0 and ftx.no=ft.no and ftx.estab=ft.estab and ftx.tipodoc=1 order by ftx.fdata desc,ftx.fno desc),0) Desc2, 
isnull((select top 1 fix.desc4 from fi(nolock) fix,ft(nolock) ftx where fix.ftstamp=ftx.ftstamp and fix.ref=fi.ref and fix.etiliquido>0 and ftx.no=ft.no and ftx.estab=ft.estab and ftx.tipodoc=1 order by ftx.fdata desc,ftx.fno desc),0) Desc4, 
isnull((select top 1 fix.etiliquido/fix.qtt from fi(nolock) fix,ft(nolock) ftx where fix.ftstamp=ftx.ftstamp and fix.ref=fi.ref and fix.etiliquido>0 and ftx.no=ft.no and ftx.estab=ft.estab and ftx.tipodoc=1 order by ftx.fdata desc,ftx.fno desc),0) Preco, 
isnull((select top 1 ftx.fdata from fi(nolock) fix,ft(nolock) ftx where fix.ftstamp=ftx.ftstamp and fix.ref=fi.ref and fix.etiliquido>0 and ftx.no=ft.no and ftx.estab=ft.estab and ftx.tipodoc=1 order by ftx.fdata desc,ftx.fno desc),0) DataPreco, 
isnull((select avg(mytable.qtt) from 
(
select ftx.no,ftx.estab,fix.ref,datepart(week,ftx.fdata) week,sum(case when ftx.tipodoc=3 then -fix.qtt else fix.qtt end) qtt 
from ft(nolock) ftx,fi(nolock) fix where ftx.ftstamp=fix.ftstamp and ftx.no=ft.no and ftx.estab=ft.estab and fix.ref=fi.ref 
and ftx.tipodoc=1 and ftx.fdata >= DATEADD(week,-11, GETDATE()) 
group by ftx.no,ftx.estab,fix.ref,datepart(week,ftx.fdata)) 
mytable 
),0) 
media_semana, 

''S''+ltrim(rtrim(str(ft.ftano)))+right('+'''0'''+'+ltrim(rtrim(str(datepart(week,ft.fdata)))),2) anomes, 
fi.qtt 

from fi,ft,st,cl 
where 
fi.ftstamp=ft.ftstamp and fi.ref=st.ref and cl.no=ft.no and cl.estab=ft.estab 
and ft.fdata >= DATEADD(week,-23, GETDATE()) 
and ft.tipodoc=1 
and fi.qtt<>0 
and cl.no='+cast(@NoCliente as nvarchar(10))+' 
and cl.estab='+cast(@NoEstab as nvarchar(10))+' 
and cl.vendnm like case when '''[email protected]+''' = '+'''TODOS'''+' then '+'''%'''+' else '''[email protected]+''' end 

) p 
PIVOT(SUM(qtt) 
     FOR anomes IN (' + @ColumnName + ')) AS PVTTable 
     order by ref' 

--Execute the Dynamic Pivot Query 
EXEC sp_executesql @DynamicPivotQuery 
+1

9倍于10 PIVOT是因为人们试图解决查询中的表示问题。有机会,你可以在代码层做很多工作,更好地用于演示。 –

+0

数据透视表在速度方面创造了奇迹,所以我不会专注于此。相反,我会去解决子查询部分。 –

+0

至少试试艾伦的建议。查询太深使查询优化器难以完成其工作。相反,填充你想要在一个临时表中转换的派生表,并在临时表上进行转换。它可能会提高性能。除此之外,你的查询在许多层面都是错误的,所以这个问题有点“太宽泛”。 –

回答

0

您是否尝试将子查询转换为临时表或表变量?

连接通常非常快,但可能很难,这取决于表格的结构以及数据集中的行数。

+0

问题是我不是tsql的专家,尽管我多年来学到了很多东西。我正在使用的这个查询是基于几个星期前我已经回答的另一篇文章,现在通过使用子查询需要更多的变量,基本上我需要最新的价格,1到4的折扣以及来自同一张表的净价格(fi)我从中获得数量。我知道的最简单的方法是通过子查询。一个联接如何更有效率?你能给我一个基于我的代码的例子吗? –

+0

如果我通过fdata desc,fno desc命令cte,我可以使用cte从那里通过一个连接从那里获得那些变量:ft.no,ft.estab和行号is = 1。它会更有效率吗? –

+0

我没有使用数据透视表。但我会查看SQL Server中的查询执行计划并确定嵌套循环的位置。当不使用子查询并添加子查询时,您应该能够看到执行计划之间的差异。 **加入排序听起来很危险,我只能加入主键和外键关系** – Joel