我有一个在其他人创建的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)
答案 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