目标:
我想加快大约一百万行事务数据(订单数据)的SQL查询。我已经能够使用CROSS APPLY()将时间从50分钟(使用临时表)减少到9分钟(参见下面的查询)。有没有办法可以消除使用ROW_NUMBER()来查找客户/年(按客户,年份分组)的最高金额支出? ROW_NUMBER()的计算成本可能很高。此外,这些表上没有索引。
码:
select z.string_customer_name, z.string_customer_region, z.string_industry_group,
z.string_city, z.string_state, z.string_country, z.string_booking_type,
z.string_sales_branch, z.string_sales_region, z.string_sales_area,
z.int_booking_year, z.float_sum_total, z.string_tpis_concat, z.string_groupby
from (
select #temp_00.*, ca_01.float_sum_total, ca_00.string_tpis_concat,
ROW_NUMBER() over (partition by #temp_00.string_groupby order by #temp_00.string_groupby,
ca_01.float_sum_total) as row_num
from #temp_00
cross apply(
select string_groupby, int_booking_year, sum(float_total) as float_sum_total
from #temp_00
group by string_groupby, int_booking_year
) as ca_01
cross apply(
select string_groupby, STRING_AGG(cast(string_customer_tpi
as varchar(max)), '|') as string_tpis_concat
from #temp_00
group by string_groupby
) as ca_00
where ca_00.string_groupby = #temp_00.string_groupby and
ca_01.string_groupby = #temp_00.string_groupby and
ca_01.int_booking_year = #temp_00.int_booking_year
) as z
where z.row_num = 1
临时表列:
string_customer_name -> 'customer name'
string_customer_tpi -> 'customer id'
string_customer_region -> 'customer region'
string_industry_group -> 'customer industry group'
string_city -> 'customer city'
string_state -> 'customer state'
string_country -> 'customer country'
string_booking_type -> 'order type'
string_sales_branch -> 'sales branch'
string_sales_region -> 'sales region'
string_sales_area -> 'sales area of the world'
int_booking_year -> 'order year'
float_total -> 'order total in dollars'
string_groupby -> 'concatenation of customer name, customer city, customer state,
customer country, customer industry group'
已发布查询的执行计划
查询的XML太大而无法发布。虽然执行计划的图片很小,但我认为第二篇文章大部分时间都在Sort()。初始数据提取和已发布查询的60%(已发布查询的成本为79%,而数据提取率为21%)在Sort()中。
我不能确定,但如果我理解你在做什么,可以避免交叉应用。这将有助于性能,但由于我没有访问数据,你必须测试它,看看。
所以我会在将数据放入临时表后开始。试试以下: -
;with TempWithSum as (
--get the sum partition by string_groupby, int_booking_year
select *,sum(float_total) over(partition by string_groupby, int_booking_year) as float_sum_total
from @temp_00
),NamesCat as(
--get all customer names grouped by string_groupby
select string_groupby, STRING_AGG(cast(string_customer_tpi as varchar(max)), '|') as string_tpis_concat
from @temp_00
group by string_groupby
),AllData as(
--get the row number partition string_groupby and ordered by string_groupby, float_sum_total
select string_customer_name, string_customer_region, string_industry_group, string_city, z.string_state,
string_country, string_booking_type, string_sales_branch, string_sales_region, string_sales_area,
int_booking_year, float_sum_total, string_tpis_concat, string_groupby
,ROW_NUMBER() over (partition by string_groupby order by string_groupby, float_sum_total) as row_num
from TempWithSum z
inner join NamesCat on NamesCat.string_groupby=TempWithSum.string_groupby
)
select * from AllData where row_num=1
希望它能够工作并在您期望的时间范围内提供您所需的结果。
注意:我知道您想要消除行号,我建议消除交叉应用,但您的目标是性能。