2016-02-26 142 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