简化嵌套查询Sql Server

时间:2018-03-06 08:01:05

标签: sql sql-server

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

    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

2 个答案:

答案 0 :(得分:3)

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

  • 要检查性能,您需要使用单个连接运行查询,并找到导致问题的连接并对其进行处理。
  • 我看到你已经使用过功能,尝试发表评论,看看你是否获得了任何性能提升。如果是,您可以使用连接等来寻找功能逻辑的集成。

  • 如果确实需要,请按顺序排列。

  • 您可以将子查询部分移动到CTE,看看是否有任何改进。

答案 1 :(得分: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 - 但请记住,输出结果并不显示函数内部发生的I / O.