在此查询中,我有什么替代方法可以进行左连接?

时间:2017-12-04 21:30:20

标签: sql-server join reporting-services

我有一个在其他人创建的SSRS报告中使用的查询。左连接是问题的原因。如果我将其更改为内连接,我会在大约15秒内得到结果(不是正确的结果)。使用Left Join我最终会在20分钟后取消查询。我为Budgets.Professionals和Transactions.Professionals添加了一个索引,性能没有变化。有没有办法重写查询而不使用左连接?

SELECT 
profs.ProfName as orig
,profs.Initials
,DATEPART(year, TransDate) as [Year]
,SUM(CASE WHEN IsFlatFee = 'Y'  OR COALESCE(MT.Admin, 'N') = 'Y' 
    THEN 0.0
    ELSE Units * (aph.assignedpercent/100) * isnull(B.rate, 0.0)
    END) AS ctp
,SUM(CASE WHEN IsFlatFee = 'Y'  OR COALESCE(MT.Admin, 'N') = 'Y' 
    THEN 0
    ELSE Units
    END * (aph.assignedpercent/100)) AS worked_hours
,SUM(Value * (aph.assignedpercent/100)) AS worked_value
, 0 AS billed_hours
,0 AS billed_value
,0 AS billed_netamt
, 0.0 as paid
, 0.0 as wo
FROM Transactions Trans 
INNER JOIN Matters Matts ON Trans.matters  = Matts.matters 
INNER JOIN MatterTypes MT ON Matts.mattertype  = MT.mattertypesdesc
and MT.Admin <> 'Y'
INNER JOIN Components Comps ON Comps.components  = Trans.components 
and Comps.CompType = 'F'
INNER JOIN AssignedProfsHistory APH on APH.Matters = Trans.Matters
and APH.AssignedType = 'Originating'
and Trans.TransDate between APH.EffectiveDate and 
ISNULL(EndDate,'12/31/2099')
INNER JOIN  Professionals profs on profs.Professionals  = APH.Professionals 
    and profs.ProfType = 'Member'
    and profs.IsActive = 'Y'
    and profs.IsBillable = 'Y'
**LEFT join** (SELECT Budgets.Professionals as timekeeper, Budgets.Amount as 
rate, Budgets.PeriodDate
FROM Matters Matts
INNER JOIN Budgets ON Matts.matters  = Budgets.matters 
    and cast(Budgets.PeriodDate as Date) <= '2017-12-31'
    AND MONTH('2017-12-31') = MONTH(Budgets.PeriodDate)
WHERE Matts.MatterID  = '99999-99.003') as B 
    *on B.timekeeper = Trans.Professionals*
    and YEAR(B.PeriodDate) = DATEPART(year, TransDate)
WHERE cast(transdate as DATE) between dateadd(day, 1, DATEADD(year, -3, 
'2017-12-31')) and '2017-12-31'
GROUP BY profs.ProfName, profs.Initials, DATEPART(year, TransDate)

3 个答案:

答案 0 :(得分:1)

肖恩和亚伦说。有太多事情可能是个问题。

您似乎(我正在猜测列名称)您正在加入文本列__init__。事实上,大多数工作都是针对文本列完成的。即使mattertypesdesc也是文字的。这在您的方案中可能无法实现,但如果表具有整数主键并且您加入了这些主键,那么它会表现得更好。

无论如何,猜测......如果你在左边的连接中用临时表替换你的子查询,你可能会获得快速的胜利。

所以在你现有的查询之前就这么做......

Matts.MatterID

然后在exisintg查询中,用

替换子查询
SELECT Budgets.Professionals as timekeeper, Budgets.Amount as rate, Budgets.PeriodDate
INTO #t
FROM Matters Matts
INNER JOIN Budgets ON Matts.matters  = Budgets.matters 
    and cast(Budgets.PeriodDate as Date) <= '2017-12-31'
    AND MONTH('2017-12-31') = MONTH(Budgets.PeriodDate)
WHERE Matts.MatterID  = '99999-99.003'

答案 1 :(得分:1)

您也可以尝试使用APPLY操作符...删除左连接&amp;它是有条件的,使用外部应用并包含外部应用脚本中的条件,如

   AND budgets.timekeeper = trans.professionals 
   AND year(budgets.perioddate) = datepart(year, transdate)

样品

OUTER APPLY
       ( 
                  SELECT     budgets.professionals AS timekeeper, 
                             budgets.amount        AS rate, 
                             budgets.perioddate 
                  FROM       matters matts 
                  INNER JOIN budgets 
                  ON         matts.matters = budgets.matters 
                  AND        cast(budgets.perioddate AS date) <= '2017-12-31' 
                  AND        month('2017-12-31') = month(budgets.perioddate) 
                  AND budgets.timekeeper = trans.professionals 
                  AND year(budgets.perioddate) = datepart(year, transdate) 
                  WHERE      matts.matterid = '99999-99.003'

                  ) AS b

答案 2 :(得分:0)

感谢所有回复的人。我接受了你的建议,我能够找到解决方案。运行2小时后我不得不杀死的查询现在在大约14秒内结束。

我最终在脚本的开头创建了一个cte。

 ;with cte as
 (SELECT Transactions FROM Transactions t
 WHERE cast(t.TransDate as DATE) between dateadd(day, 1, DATEADD(year, -3, 
 @EndDate)) and @EndDate)

然后我将CTE链接到交易。

FROM Transactions Trans
INNER JOIN cte ON cte.Transactions = Trans.Transactions 

然后,我就可以删除&#39;其中&#39;导致问题的条款。

WHERE cast(transdate as DATE) between dateadd(day, 1, DATEADD(year, -3, 
@EndDate)) and @EndDate