【问题标题】:Improving Performance of CTE提高 CTE 的性能
【发布时间】:2020-11-30 11:13:08
【问题描述】:

我需要一份报告,计算不同表格中的一些值。
我正在使用 CTE 和子查询进行计算,但查询速度很慢。
我尝试了一些尝试来提高性能,但没有成功。
实际查询有更多列,但我复制了其中的一部分以了解我的查询结构。
感谢您的帮助。

begin
with CTE_FirmList
(
    FirmId,
    FirmName,
    StartDate,
    EndDate,
    TgId,
    TgName,
    TgCity,
    ProjectName
)
as
(
    select 
        distinct f.Id FirmId,
        f.Name FirmName,
        f.StartDate,
        f.EndDate,
        t.Id TgId,
        t.Name TgName,
        c.Name TgCity,
        p.Name ProjectName
    from Firm f
        left join Tg t on t.Id = f.TgId
        left join City c on c.Id=t.CityId 
        left join Country co on co.Id=f.CountryId
        left join FirmProject p on p.FirmId=f.Id
)

select
    FirmId,
    FirmName,
    
    (select COUNT(0) 
    from FirmPersonnel p 
        inner join CTE_FirmList f on f.FirmId=p.FirmId
    where f.FirmId=qq.FirmId
    ) TotalPersonnelCount,
    
    (select COUNT(0) 
    from FirmPersonnel p 
        inner join CTE_FirmList f on f.FirmId=p.FirmId 
    where f.FirmId=qq.FirmId and p.PersonnelType in (1) 
    ) PersonnelCount1,

    (select COUNT(0) 
    from FirmPersonnel p 
        inner join CTE_FirmList f on f.FirmId=p.FirmId 
    where f.FirmId=qq.FirmId and p.PersonnelType in (2) 
    ) PersonnelCount2,
            
    (select count(p.Id) 
    from FirmProject p 
    where p.FirmId=qq.FirmId
    ) TotalProjectCount,
    
    (select count(p.Id) 
    from FirmProject p 
    where p.FirmId=qq.FirmId
        and p.ProjeStatus in (1)
    ) ProjectCount1,
    
    (select count(p.Id) 
    from FirmProject p 
    where p.FirmId=qq.FirmId
        and p.ProjeStatus in (2)
    ) ProjectCount2
from CTE_FirmList qq
where ProjectName like '%search condition%'
order by TgCity,TgName,FirmName
end

这是示例数据和所需的输出:



【问题讨论】:

  • 请提供样本数据、期望的结果以及表格大小的一些想法。
  • 所有这些子查询都可能成为竞争者。也许一些条件聚合在这里会有所帮助(看起来对某些人来说肯定会),但示例数据和预期结果将真正帮助我们帮助您。
  • 在子查询之后我不是子查询的忠实拥护者...从未体验过良好的性能...但是,您可以尝试以下操作:SELECT c.FirmID, c.FirmName, COUNT(CASE p.ID IS NOT NULL THEN 1 ELSE NULL END) AS TotalPersonalCount, COUNT(CASE WHEN p1.ID IS NOT NULL THEN 1 ELSE NULL END) AS PersonalCount1, ... FROM cte c LEFT JOIN FirmPersonnel p ON c.FirmID = p.ID LEFT JOIN FirmPersonnel p1 ON ... GROUP BY FirmID, FirmName
  • @GordonLinoff 我用示例数据和输出进行了编辑。公司有10k,项目有50k,人员有200k记录

标签: sql sql-server performance subquery common-table-expression


【解决方案1】:

您绝对可以简化查询。这有点难以理解,但这样的东西应该有更好的性能:

select f.FirmId, f.FirmName,
       p.TotalPersonnelCount, p.PersonnelCount1, p.PersonnelCount2
       count(distinct ProjectId) as TotalProjectCount,
       count(distinct case when ProjectStatus = 1 then ProjectId end) as ProjecctCount1,
       count(distinct case when ProjectStatus = 2 then ProjectId end) as ProjecctCount2
from (select f.Id as FirmId, f.Name as FirmName, f.StartDate, f.EndDate,
             t.Id TgId, t.Name as TgName, c.Name as TgCity,
             p.Name as ProjectName, p.ProjectId, p.status
      from Firm f left join
           Tg t
           on t.Id = f.TgId join
           City c
           on c.Id = t.CityId left join
           Country co
           on co.Id = f.CountryId left join
           FirmProject p
           on p.FirmId = f.Id
       where p.name like '%search condition%'
      ) fp join
      (select p.FirmId, count(*) as TotalPersonnelCount,
              sum(case when PersonnelType in (1) then 1 else 0 end) as PersonnelCount1, 
              sum(case when PersonnelType in (2) then 1 else 0 end) as PersonnelCount2
       from FirmPersonnel p 
       group by fp.FirmId 
      ) p
      on fp.FirmId = p.FirmId
group by FirmId, FirmName
order by FirmName

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 2010-10-15
    相关资源
    最近更新 更多