简化嵌套查询Sql Server

问题描述 投票:1回答:2

如何简化嵌套查询?有一些与此查询相关的性能问题

    select
    t.GroupName as ProviderName,
    t.GroupName as Groupname,
    t.idPriceGroup,
    sum(t.fixed_value) as fixed_value,
    avg(isnull(t.percent_value, 0)) as percent_value, 
    isnull(sum(amount), 0) as amount, 
    sum(case when Include2SpecTotal = 1 then isnull(amount,0) else 0 end) as AmountSpecial,
    isnull(sum(bonus_total), 0) as bonus_total,
    isnull(sum(bonus_landlord), 0) as bonus_landlord,
    sum(case when Include2SpecTotal = 1 then isnull(bonus_landlord,0) else 0 end) as bonus_landlordSpecial
from
    (
        SELECT 
            ISNULL(dbo.fn_GetProviders_str(p.idLocalize, 'EN'), 'Test Service') as ProviderName, 
            idSupplier,
            r.idProvider,
            alias,
            isnull(amount, 0) amount, 
            isnull(bonus_total, 0) bonus_total,
            isnull(bonus_landlord, 0) bonus_landlord, 
            (SELECT idPriceGroup FROM dbo.fn_GetPricelistGroupForProvider(r.idSupplier, r.alias)) as idPriceGroup, 
            (SELECT [name] FROM dbo.fn_GetPricelistGroupForProvider(r.idSupplier, r.alias)) as GroupName, 
            (SELECT Include2SpecTotal FROM dbo.fn_GetPricelistGroupForProvider(r.idSupplier, r.alias)) as Include2SpecTotal, 
            isnull(fixed_value, 0)
            fixed_value,
            isnull(percent_value, 0) percent_value  
        FROM ReportTurnoverItems r
            left join providers p ON r.idSupplier = p.idProviderExternal AND r.idProvider = p.idProvider
        WHERE CHARINDEX(',' + cast(idReportTurnover as varchar) + ',', + ',' + @idReportTurnover+',') > 0
    ) t 
group by
    t.GroupName,
    t.idPriceGroup,
    t.Include2SpecTotal
order by
    avg(isnull(t.percent_value, 0)) desc,
    t.GroupName,
    t.idPriceGroup
sql sql-server
2个回答
1
投票

您应该这样做,而不是多次调用该函数:

select
    ....
    PGP.idPriceGroup, 
    PGP.name,
    PGP.Include2SpecTotal
    ...
FROM 
    ReportTurnoverItems r
    left join providers p ON r.idSupplier = p.idProviderExternal AND r.idProvider = p.idProvider
    outer apply dbo.fn_GetPricelistGroupForProvider(r.idSupplier, r.alias) PGP

猜测fn_GetPricelistGroupForProvider是一个多语句函数,因此您应该考虑将其转换为内联函数。

其他问题当然是这样的:

WHERE CHARINDEX(',' + cast(idReportTurnover as varchar) + ',', + ',' + @idReportTurnover+',') > 0

SQL Server不会使用任何索引 - 这看起来像是以错误的方式设计了数据库,在单个字段中有一个值列表。

为了确定实际问题是什么,你应该研究sys.dm_exec_query_stats并使用set statistics io on - 但是请记住统计信息io输出并不显示函数内部发生的I / O.


3
投票

有多种方法可以做到这一点。

  • 要检查性能,您需要使用单个连接运行查询,并找到导致问题的连接并对其进行处理。
  • 我看到你已经使用过功能,尝试发表评论,看看你是否获得了任何性能提升。如果是,您可以使用连接等来寻找功能逻辑的集成。
  • 如果真的需要,请保持秩序。
  • 您可以将子查询部分移动到CTE,看看是否有任何改进。
© www.soinside.com 2019 - 2024. All rights reserved.