Ich habe diese Abfrage, die in einem SSRS-Bericht verwendet wird, den jemand anders erstellt hat. Der linke Join ist die Ursache des Problems. Wenn ich es zu einem inneren Join ändere, erhalte ich Ergebnisse (nicht die korrekten Ergebnisse) in ungefähr 15 Sekunden. Mit dem Linksbündnis beende ich die Abfrage nach 20 Minuten. Ich habe einen Index zu Budgets.Professionals und Transactions.Professionals ohne Leistungsänderung hinzugefügt. Gibt es eine Möglichkeit, die Abfrage neu zu schreiben und nicht die linke Verknüpfung zu verwenden?Welche Alternative habe ich zu einer Left Join in dieser Abfrage?
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)
Es gibt kaum eine Chance, dass jemand mit so wenig Informationen helfen kann. Wir müssten Tabellendefinitionen einschließlich Indizes zusammen mit ungefähren Zeilenzahlen für alle beteiligten Tabellen sehen. Außerdem würde ein Ausführungsplan helfen, aber da Sie die Abfrage nicht abschließen können, ist das möglicherweise nicht möglich. –
Es gibt einige sichtbare Kuriositäten, wie zum Beispiel, warum Sie als date 'cast (Budgets.PeriodDate als Date) 'casten, und dann eine Datumsfunktion auf demselben Feld ohne einen' MONTH (Budgets.PeriodDate) '- Cast ausführen. Sie sollten die Funktionen in where/join immer sorgfältig ausführen, da sie die Verwendung von Indizes ungültig machen können. Sonst, was Sean gesagt hat. –
Meine Vermutung wäre, dass es keine Indizes für die LEFT JOINed-Tabelle verwendet.Vermutlich haben Sie einen Index auf Budgets.PeriodDate, aber bevor Sie versuchen, die Spalte (und den zugehörigen Index) zu verwenden, machen Sie eine CAST darauf. An diesem Punkt hat der Optimierer keine Ahnung mehr, dass der neue Wert der gleiche wie der Index ist, weil es nicht sein könnte. Wir müssen auf jeden Fall Ihre Tabellenstruktur, Indizes und die geschätzten Ausführungspläne sehen (da, wie Sean sagte, Sie nicht die tatsächlichen haben werden). – indiri