Sql server 在这个查询中,除了左连接,我还有什么选择?
我在其他人创建的SSRS报告中使用了这个查询。左连接是问题的原因。如果我将其更改为内部联接,我将在大约15秒内得到不正确的结果。使用左连接,我在20分钟后取消了查询。我在预算、专业人员和交易中都添加了一个索引,专业人员的绩效没有变化。有没有办法重写查询而不使用左连接Sql server 在这个查询中,除了左连接,我还有什么选择?,sql-server,join,reporting-services,Sql Server,Join,Reporting Services,我在其他人创建的SSRS报告中使用了这个查询。左连接是问题的原因。如果我将其更改为内部联接,我将在大约15秒内得到不正确的结果。使用左连接,我在20分钟后取消了查询。我在预算、专业人员和交易中都添加了一个索引,专业人员的绩效没有变化。有没有办法重写查询而不使用左连接 SELECT profs.ProfName as orig ,profs.Initials ,DATEPART(year, TransDate) as [Year] ,SUM(CASE WHEN IsFlatFee = 'Y'
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)
正如肖恩和亚伦所说。有太多潜在的问题 你似乎是我从列名猜到你加入了mattertypesdesc文本列。事实上,大部分工作都是针对文本列进行的。甚至Matts.MatterID也是文本。这在您的场景中可能不可能实现,但如果表具有整数主键,并且您在这些主键上进行连接,则性能会更好 不管怎么说,猜猜看。。。。如果用临时表替换左侧联接中的子查询,您可能会很快获得成功 所以,在您执行现有查询之前
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'
您也可以尝试使用APPLY操作符。。。删除左连接&它是on条件,使用outerapply并在outerapply脚本中包含on条件,如
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小时后不得不终止的查询现在大约在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
然后,我能够删除导致问题的“where”条款
WHERE cast(transdate as DATE) between dateadd(day, 1, DATEADD(year, -3,
@EndDate)) and @EndDate
任何人都不可能在如此少的信息上提供帮助。我们需要查看表定义,包括索引以及此处涉及的所有表的近似行数。此外,执行计划也会有所帮助,但由于您无法完成查询,这可能是不可能的。有一些明显的奇怪之处,例如,为什么您将日期转换为日期castBudgets.PeriodDate转换为日期,然后在同一字段上执行日期函数,而不使用转换MONTHBudgets.PeriodDate。在where/join中执行函数时应始终小心,因为它们可能会使任何索引的使用无效。否则,肖恩是这么说的。我猜它没有在左联接表上使用任何索引。假设您在Budgets.PeriodDate上有一个索引,但在尝试使用该列和关联索引之前,您正在对其进行转换。此时,优化器不再知道新值与索引相同,因为它可能不相同。我们肯定需要查看您的表结构、索引和估计的执行计划,因为正如Sean所说,您不会得到实际值。
WHERE cast(transdate as DATE) between dateadd(day, 1, DATEADD(year, -3,
@EndDate)) and @EndDate