declare @SQL nvarchar(max)
,@Columns1 nvarchar(max)
,@Columns2 nvarchar(max);
set @Columns1 = N'';
set @Columns2 = N'';
select @Columns1 += iif(@Columns1 = '',quotename(Columns1),N','+quotename(Columns1))
from (select Month+' Count of TonerQty' as Columns1
from MPSSell
where Month is not null
and Month != ''
and Country in(select *
from [dbo].[UF_CSVToArray]('Hong Kong,South Korea,New Zealand,Philippines,Australia,India')
)
group by Month
) as colPvt1;
select @Columns2 += iif(@Columns2 = '',quotename(Columns2),N','+quotename(Columns2))
from
(select Month+' Count of PL' as Columns2
from
MPSSell
where Month is not null
and Month != ''
and Country in(select *
from [dbo].[UF_CSVToArray]('Hong Kong,South Korea,New Zealand,Philippines,Australia,India')
)
group by Month
) as colPvt2;
set @SQL = N'
select result1.Country
,['+stuff(@Columns1,1,1,'')
+', ['+stuff(@Columns2,1,1,'')
+' from(SELECT *
FROM (Select Country
,Month + '' Count of TonerQty'' as Columns1
,TonerQty as opValue1
from MPSSell
where Country is not null
and Country != ''''
and Month is not null
and Month != ''''
and Country in(Select *
from [dbo].[UF_CSVToArray](''Hong Kong,South Korea,New Zealand,Philippines,Australia,India'')
)
group by Country
,Month
,TonerQty
) as resPvt1
PIVOT(Count(opValue1) FOR Columns1 IN( ['+stuff(@Columns1,1,1,'')+')) as p
) as result1
join (SELECT *
FROM (Select Country
,Month + '' Count of PL'' as Columns2
,PL as opValue2
from MPSSell
where Country is not null
and Country != ''''
and Month is not null
and Month != ''''
and Country in(Select *
from [dbo].[UF_CSVToArray](''Hong Kong,South Korea,New Zealand,Philippines,Australia,India'')
)
group by Country
,Month
,PL
) as resPvt2
PIVOT(Count(opValue2) FOR Columns2 IN ( ['+stuff(@Columns2,1,1,'')+')) as p
) as result2
on result1.Country=result2.Country';
exec sp_executesql
@SQL;
这是我的SQL数据透视查询工作正常,但执行时间太长。请帮助我如何减少执行时间。
Estimated Execution plan in Google Drive
答案 0 :(得分:2)
注意WHERE ... IN (SELECT...)
,不要多次做同样的事情,帮助服务器了解你想要实现的目标:
declare @countries table (country <actual type>)
insert into @countries (country)
Select <actual col>
from [dbo].[UF_CSVToArray](''Hong Kong,South Korea,New Zealand,Philippines,Australia,India'')
之后到处使用:
...
where exists(select 1 from @countries cc where cc.country = mps.country)
...
两个查询的来源之间有什么区别?无。
select @Columns1 += iif(@Columns1 = '',quotename(Columns1),N','+quotename(Columns1))
from (select Month+' Count of TonerQty' as Columns1
from MPSSell
where Month is not null
and Month != ''
and Country in(select *
from [dbo].[UF_CSVToArray]('Hong Kong,South Korea,New Zealand,Philippines,Australia,India')
)
group by Month
) as colPvt1;
select @Columns2 += iif(@Columns2 = '',quotename(Columns2),N','+quotename(Columns2))
from
(select Month+' Count of PL' as Columns2
from
MPSSell
where Month is not null
and Month != ''
and Country in(select *
from [dbo].[UF_CSVToArray]('Hong Kong,South Korea,New Zealand,Philippines,Australia,India')
)
group by Month
) as colPvt2;
转换为
select @Columns1 += iif(@Columns1 = '',quotename(Month+' Count of TonerQty'),N','+quotename(Month+' Count of TonerQty')),
@Columns2 += iif(@Columns2 = '',quotename(Month+' Count of PL'),N','+quotename(Month+' Count of PL'))
from
(select DISTINCT Month
from MPSSell mps
where Month is not null
and Month != ''
and exists(select 1 from @countries cc where cc.country = mps.country)
) as colPvt2;
现在您只扫描源表中的月份列表一次。
从其他地方获取月份列表(缓存,参数,更短的表)。并且只扫描源表一次 - 在最后检索数据的位置。
答案 1 :(得分:0)
使用PIVOT
子句的某些数据透视查询可以从HASH GROUP
查询提示中受益。尝试在动态查询结束时指定OPTION(HASH GROUP)
。有关详细信息,请参阅Query Hints。
另一个可能的性能改进是不使用PIVOT
子句来转动,而是转向老式的方式。如果您在互联网上搜索sql server old-school pivot
,可以找到几个这样的例子,但这里有关于Stack Overflow的one example如何完成。