摆脱昂贵的自我加入

时间:2016-09-17 17:06:55

标签: sql sql-server

我有一个像这样的SQL语句

SELECT  
    pa.col1,
    SUM(ps.col2) col2,
    SUM(psl.col2) col2_previous_month
FROM  
    pa
LEFT JOIN 
    ps ON pa.Id = ps.Id AND ps.date = @currDate
LEFT JOIN 
    ps as psl ON psl.Id = ps.Id AND psl.date = dateadd(month, - 1, @currDate)
GROUP BY 
    pa.col1;

经常调用此SQL,因为表ps有100M行,所以左连接会受到影响。有没有办法用左连接重写这​​个?

此致 尼克

3 个答案:

答案 0 :(得分:2)

也许这会有所帮助

    Select pa.col1
          ,col2      =isnull(sum(case when ps.date=@currDate                   then ps.col2 else null end),0)
          ,col2_prior=isnull(sum(case when ps.date=dateadd(month,-1,@currDate) then ps.col2 else null end),0)
     From pa
     JOIN ps as ps ON pa.Id  = ps.Id 
      and ps.date in (@currDate,dateadd(month,-1,@currDate))
     Group By pa.col1

答案 1 :(得分:1)

如果John的查询没有帮助,您也可以试试这个:

SELECT  
    pa.col1
    ,SUM(ps1.col2) col2
    ,SUM(ps2.col2) col2_previous_month

FROM  pa

    LEFT JOIN 
        (
            SELECT col2
            FROM ps
            WHERE date = @currDate
        ) ps1 ON ON pa.Id = ps1.Id        

     LEFT JOIN 
        (
            SELECT col2
            FROM ps
            WHERE date = dateadd(month, - 1, @currDate)
        ) ps2 ON ON pa.Id = ps2.Id

GROUP BY pa.col1;

在读完你的评论后我想到了。

除了我在嵌套查询中的日期上移动搜索之外,它与初始查询完全相同,这可能有助于优化器正确使用索引。

答案 2 :(得分:0)

查询看起来很好。为了使其快速执行,您应该具有以下索引:

  • pa(id)
  • ps(id,date)

如果您希望它更快,请使用覆盖索引:

  • pa(id,col1)
  • ps(id,date,col2)