Temp table throws invalid object name after adding 'SET SHOWPLAN_ALL' Sql Server MS17 - sql

I'm fairly new to SQL Server and I've been assigned the task of optimizing some SQL Queries generated by a CMS. After I add the code
SET SHOWPLAN_ALL ON
GO;
and execute the query, the local temp table #tempSecondLevel throws an 'invalid object name' exception in my INSERT INTO statement. You will see a SELECT INTO #tmpSecondLevel statement and then an INSERT INTO #tmpSecondLevel statement. The next statements are for #tmpFirstLevel, and I'm not sure if those are relevant to this question.
use Kentico8_2;
go
set showplan_all on;
go
-- Write revised query here.
DECLARE #ProductNodeGuid uniqueidentifier = '6F6F733D-AE4F-47DC-9BE9-52B967E9F41D'
IF OBJECT_ID('tempdb..#tmpSecondLevel') IS NOT NULL
DROP TABLE #tmpSecondLevel
IF OBJECT_ID('tempdb..#tmpFirstLevel') IS NOT NULL
DROP TABLE #tmpFirstLevel
-- Get all of the items(that go on the secondLevel) that go underneath a heading(on the firstLevel)
-- Get all of the materials that belong to this node that go on the second level
SELECT
NodeLevel = 1
,NodeParentID = CASE WHEN MaterialTypeSelectByMaterial = 0 THEN M.NodeID ELSE M.NodeParentID END
,M.NodeID
,M.MaterialName
,MaterialImage = MV.MaterialVariantImage
,M.NodeAliasPath
,M.Published
,M.NodeGUID
,M.ClassName
,M.NodeOrder
INTO
#tmpSecondLevel
FROM
View_NOF_Material_Joined M
JOIN View_NOF_Product_Joined P
ON P.ProductMaterialNodeGuidList LIKE '%' + CONVERT(nvarchar(36), M.NodeGUID) + '%'
JOIN View_NOF_MaterialType_Joined MT
ON MT.NodeID = M.NodeParentID
LEFT JOIN View_NOF_MaterialVariant_Joined MV
ON MV.NodeParentID = M.NodeID AND MV.NodeOrder = 1 -- always the first
WHERE
P.NodeGUID = #ProductNodeGuid AND MaterialTypeSelectByMaterial = 1
-- Get all of the material variants that belong to this node that go on the second level
INSERT INTO
#tmpSecondLevel
SELECT
NodeLevel = 1
,NodeParentID = CASE WHEN MaterialTypeSelectByMaterial = 0 THEN M.NodeID ELSE M.NodeParentID END
,MV.NodeID
,MaterialName = MV.MaterialVariantName
,MaterialImage = MV.MaterialVariantImage
,MV.NodeAliasPath
,MV.Published
,MV.NodeGUID
,MV.ClassName
,MV.NodeOrder
FROM
View_NOF_MaterialVariant_Joined MV
JOIN View_NOF_Product_Joined P
ON P.ProductMaterialNodeGuidList LIKE '%' + CONVERT(nvarchar(36), MV.NodeGUID) + '%'
JOIN View_NOF_Material_Joined M
ON M.NodeID = MV.NodeParentID
JOIN View_NOF_MaterialType_Joined MT
ON MT.NodeID = M.NodeParentID
WHERE
P.NodeGUID = #ProductNodeGuid
AND MaterialTypeSelectByMaterial = 0
-- Get all of the headings( for the firstLevel) that go above a list of items(on the secondLevel)
-- Get all of the material types that are used as headings
SELECT DISTINCT
NodeLevel = 0
,NodeParentID = NULL
,MT.NodeID
,MaterialName = MT.MaterialTypeName
,MaterialImage = ''
,MT.NodeAliasPath
,MT.Published
,MT.NodeGUID
,MT.ClassName
,MT.NodeOrder
INTO
#tmpFirstLevel
FROM
View_NOF_MaterialType_Joined MT
INNER JOIN #tmpSecondLevel M
ON MT.NodeID = M.NodeParentID
-- Get all of the materials that are used as headings
INSERT INTO
#tmpFirstLevel
SELECT DISTINCT
NodeLevel = 0
,NodeParentID = NULL
,MJ.NodeID
,MaterialName = MJ.MaterialName
,MaterialImage = ''
,MJ.NodeAliasPath
,MJ.Published
,MJ.NodeGUID
,MJ.ClassName
,MTJ.NodeOrder
FROM
View_NOF_Material_Joined MJ
INNER JOIN View_NOF_MaterialType_Joined MTJ
ON MTJ.NodeID = MJ.NodeParentID
INNER JOIN #tmpSecondLevel M
ON MJ.NodeID = M.NodeParentID
-- Put all of the second level items (the details) and first level items (the headings) in the same table
SELECT * FROM #tmpSecondLevel
UNION
SELECT * FROM #tmpFirstLevel
ORDER BY NodeOrder
IF OBJECT_ID('tempdb..#tmpSecondLevel') IS NOT NULL
DROP TABLE #tmpSecondLevel
IF OBJECT_ID('tempdb..#tmpFirstLevel') IS NOT NULL
DROP TABLE #tmpFirstLevel
I predict this is a simple question to ask since I only added two lines of code, but the help is much appreciated. If you have any tips for me about optimizing these queries, that is greatly appreciated as well.
Thanks in advance.

You are getting the error because SET SHOWPLAN_ALL is the command to show Estimated execution plans. Therefore no TSQL commands are actually executed, and thus the #tmpSecondLevel table is never created. So you get an error. This would be the same thing as clicking the "Display Estimated Execution Plan" in SSMS.
You can read about that command here: https://learn.microsoft.com/en-us/sql/t-sql/statements/set-showplan-all-transact-sql
If you want to show the Actual execution replace SHOWPLAN_ALL line with SET STATISTICS XML ON. This will display the actual execution plan when you run the query.

Related

SQL query running slowly - parameter sniffing

I have a simple query where I return a list of orders by date range. This query is used in a report which feeds it parameters(Site, From Date, and To Date).
ALTER PROCEDURE [dbo].[Z_N_ECOM_ORDER_STATUS_DATERANGE]
#Site VARCHAR(5),
#FromDate DATETIME,
#ToDate DATETIME
AS
BEGIN
SET NOCOUNT ON;
SELECT
o.Company_Code,
o.Division_Code,
o.Control_Number,
RTRIM(o.Customer_Purchase_Order_Number) AS Shopify_Num,
CASE
WHEN p.PickTicket_Number IS NULL
THEN i.PickTicket_Number
ELSE p.PickTicket_Number
END PickTicket_Number,
i.Invoice_Number,
o.Date_Entered,
CASE
WHEN ph.packslip IS NULL AND i.invoice_number IS NULL
AND P.pickticket_number IS NULL
THEN 'Cancelled'
WHEN ph.packslip IS NULL AND i.invoice_number IS NULL
AND DATEADD(minute, 90, o.date_entered) > CURRENT_TIMESTAMP
THEN 'Not Entered Yet'
WHEN ph.packslip IS NULL
THEN 'SHIPPED & UPLOADED'
ELSE RTRIM (z.status)
END Accellos_Status,
b.UPS_Tracking_Number Tracking_Number
FROM
[JMNYC-AMTDB].[AMTPLUS].[dbo].Orders o (nolock)
LEFT JOIN
[JMNYC-AMTDB].[AMTPLUS].[dbo].PickTickets p (nolock) ON o.Company_Code = p.Company_Code
AND o.Division_Code = p.Division_Code
AND o.Control_Number = p.Control_Number
LEFT JOIN
[JMNYC-AMTDB].[AMTPLUS].[dbo].Invoices i (nolock) ON o.Company_Code = i.Company_Code
AND o.Division_Code = i.Division_Code
AND o.Control_Number = i.Control_Number
LEFT JOIN
[JMNYC-AMTDB].[AMTPLUS].[dbo].box b (nolock) ON o.Company_Code = b.Company_Code
AND o.Division_Code = b.Division_Code
AND i.PickTicket_Number = b.PickTicket_Number
LEFT JOIN
pickhead ph (nolock) ON p.PickTicket_Number = ph.packslip
LEFT JOIN
Z_Status z (nolock) ON ph.PROCSTEP = z.procstep
WHERE
o.Company_Code = LEFT(#Site, 2)
AND o.Division_Code = RIGHT(#Site, 3)
AND o.Customer_Number = 'ecom2x'
AND o.Date_Entered BETWEEN #FromDate AND DATEADD(dayofyear, 1, #ToDate)
ORDER BY
o.date_entered DESC
END
The problem with this query is that it takes way too long and the problem lines are
WHERE
o.Company_Code = LEFT(#Site, 2)
AND o.Division_Code = RIGHT(#Site, 3)
The format of the variable site is something like '09001' or '03001' where the left side is the company and the right side is the division
Because when I run this query with hard-coded values, it runs pretty much instantaneously. When I use the parameters, it takes minutes.
So I looked it up and I discovered about parameter sniffing. So I added the following line after the begin statement.
DECLARE #LocalSite VARCHAR(5) = CAST(#Site AS VARCHAR(5))
However, it still runs extremely slow.
My new where statement would be
WHERE
o.Customer_Number = 'ecom2x'
AND o.Date_Entered BETWEEN #FromDate AND DATEADD(dayofyear, 1, #ToDate)
AND ((#LocalSite = '00000') OR (O.Company_Code = LEFT(#LocalSite, 2) AND O.Division_Code = RIGHT(#LocalSite, 3)))
order by o.date_entered desc*
I also want the user to have the functionality of selecting all sites which will make the site variable be '00000' and thus it shouldn't run the company/division code check. This current where statement makes the query run very slow.
Does anyone know what I am doing wrong?
Can you try to avoid using LEFT() and RIGHT() by declaring few variables and assigning values to those variables and then using them in the SELECT statement?
a hint OPTIMIZED FOR UNKNOWN to avoid parameter sniffing:
option (OPTIMIZE FOR (#p1 UNKNOWN, #p2 UNKNOWN))
Where p1 and p2 those two variables mentioned above
I also want the user to have the functionality of selecting all sites
which will make the site variable be '00000' and thus it shouldn't run
the company/division code check. This current where statement makes
the query run very slow.
This can be optimized by replacing current SELECT with IF statement that uses two SELECTs. If value is 00000 just avoid to check on company and division, else run the same select but with those extra checks
Another striking thing is querying linked server objects with further join to local tables. Consider to split this into a separate step, for instance by storing data in temporary table (not a table variable!) as intermediate result. Then temp table to be joined with local objects. This can improve accuracy of query plan because of better estimates.
Did you try taking left and right values of#site parameter in two different variables and using those variables in SP.
For eg.
Declare #compcode as varchar(2)
Declare #divcode as varchar(3)
Set #compcode=LEFT(#Site, 2)
Set #divcode=RIGHT(#Site, 3)
Your where condition
WHERE
o.Company_Code = #compcode
AND o.Division_Code = #divcode

Literal vs variable in T-SQL query with view produces vastly different query time

When I use a literal in a WHERE clause in a query against a view, the result is basically instantaneous. When I use a variable set to that same value, a completely different and very slow query plan takes its place. How is this possible? How can these be vastly different:
DECLARE #a INT = 5
SELECT ...
WHERE myview.mycol = #a
vs
SELECT ...
WHERE myview.mycol = 5
Here is the exact query and timing that I am encountering (I can post additional information about the view itself, but I don't know that posting the view definition itself is that useful: it is complex and relies on a dozen other views and tables. I can post it if it's helpful in answering the question.)
DECLARE #productdbuid INT = 5
DECLARE #t1 DATETIME;
DECLARE #t2 DATETIME;
---------------------
SET #t1 = GETDATE();
SELECT
*
FROM
vwPublishingActions
WHERE
productdbuid = 5 AND storedbuid = 1
SET #t2 = GETDATE();
SELECT DATEDIFF(MILLISECOND,#t1,#t2) time1;
---------------------
SET #t1 = GETDATE();
SELECT
*
FROM
vwPublishingActions
WHERE
productdbuid = #productdbuid AND storedbuid = 1
SET #t2 = GETDATE();
SELECT DATEDIFF(MILLISECOND,#t1,#t2) time2;
time1: 13
time2: 2796
What is causing SQL Server to treat the literal 5 so differently from #productbuid INT = 5?
Thanks so much for any guidance.
UPDATE: I've been asked to include the view definition:
SELECT
T2.productdbuid,
T2.storedbuid,
ISNULL(paca.publishactiondbuid, 8) publishingaction, -- 8 = ERROR_REPORT
T2.change_product,
T2.change_price,
T2.change_stockstatus,
T2.inventory_belowtrigger,
T2.ruledbuid ruledbuid
FROM
(SELECT
T.productdbuid,
T.storedbuid,
-- pick first fully matching set of conditions
(SELECT TOP 1 paca.dbuid
FROM dbo.z_PublishingActionCalcs paca
WHERE (paca.storetypedbuid = T.storetypedbuid)
AND (paca.publishingcommanddbuid = T.publishcommanddbuid OR paca.publishingcommanddbuid IS NULL)
AND (ISNULL(paca.publishingstatusdbuid, 0) = ISNULL(T.publishstatusdbuid, 1007) OR paca.publishingstatusdbuid IS NULL) -- 1007 = NOTSET
AND (ISNULL(ABS(paca.change_product),0) = ISNULL(ABS(T.change_product),0) OR paca.change_product IS NULL)
AND (ISNULL(ABS(paca.change_price),0) = ISNULL(ABS(T.change_price),0) OR paca.change_price IS NULL)
AND (ISNULL(ABS(paca.change_stockstatus),0) = ISNULL(ABS(T.change_stockstatus),0) OR paca.change_stockstatus IS NULL)
AND (ISNULL(ABS(paca.inventory_belowtrigger),0) = ISNULL(ABS(T.inventory_belowtrigger),0) OR paca.inventory_belowtrigger IS NULL)
AND (ISNULL(paca.stockstatusdbuid, 0) = ISNULL(T.stockstatusdbuid, 0) OR paca.stockstatusdbuid IS NULL)
ORDER BY paca.sort) ruledbuid,
ABS(ISNULL(T.change_product,0)) change_product,
ABS(ISNULL(T.change_price,0)) change_price,
ABS(ISNULL(T.change_stockstatus,0)) change_stockstatus,
ABS(ISNULL(T.inventory_belowtrigger,0)) inventory_belowtrigger
FROM
(SELECT
p.productid,
s.storetypedbuid,
CASE
WHEN pdpcm.publishcommanddbuid <> 4
THEN NULL -- STOCKSTATUS
ELSE pss.stockstatusdbuid
END product_stockstatus,
CASE
WHEN pdpcm.publishcommanddbuid <> 5
THEN NULL -- INVENTORY
ELSE itr.inventory_belowtrigger
END inventory_belowtrigger,
p.dbuid productdbuid,
s.dbuid storedbuid,
pdpc.change_product,
pdpc.change_price,
pdpc.change_stockstatus,
pdpcm.publishcommanddbuid,
pdps.publishstatusdbuid,
pss.stockstatusdbuid
FROM
dbo.ProductDetailsPublishingCommands pdpcm
INNER JOIN
dbo.Stores s ON s.dbuid = pdpcm.storedbuid
INNER JOIN
dbo.Products p ON pdpcm.productdbuid = p.dbuid
INNER JOIN
dbo.StoreTypeSet st ON st.dbuid = s.storetypedbuid
LEFT JOIN
dbo.vwPublishingChanges pdpc ON pdpc.productdbuid = p.dbuid
AND pdpc.storedbuid = s.dbuid
LEFT JOIN
dbo.ProductDetailsPublishingStatuses pdps ON pdps.productdbuid = p.dbuid
AND pdps.storedbuid = s.dbuid
LEFT JOIN
dbo.vwProductStockStatus pss ON pss.productdbuid = p.dbuid
LEFT JOIN
dbo.vwProductInventory pri ON pri.productdbuid = p.dbuid
LEFT JOIN
dbo.vwInventoryTriggers itr ON itr.storedbuid = s.dbuid
AND itr.productdbuid = p.dbuid) T
) T2
LEFT JOIN
dbo.z_PublishingActionCalcs paca ON T2.ruledbuid = paca.dbuid
You would need to look at the execution plan to be sure.
When you use a variable mycol = #a SQL Server will create a plan based on average column density for values in mycol.
The mycol = 5 predicate may be significantly above or below the average. When you use a literal SQL Server can lookup the value 5 in the column statistics and potentially get more accurate estimates and thus a more appropriate plan.
Additionally using a literal can allow some additional optimisations and simplifications.
An example is that a view with a PARTITION BY mycol can have the literal predicate pushed further down than a variable or parameter generally can (except when using OPTION (RECOMPILE)).
Additionally with the literal value available at compilation SQL Server may be able to simplify expressions and use contradiction detection to eliminate some of the work at run time.

Function with in clause in where condition of SP decreasing the procedure performance

I have a procedure that has following functions in where condition:
select col1,col2,col3...
from table1
where
(dbo.GetFilStatus(et.SgDate,et.Speed,(SELECT COUNT(J.JId) FROM tbl_Nt J
inner JOIN tbl_NAssign JN ON JN.NNo =J.NNo
inner JOIN dbo.tbl_CStatus JS ON JS.CStatusID=J.CStatusID
INNER JOIN dbo.tbl_SStatus ss ON ss.SStatusID=JS.SStatusID
WHERE JN.DriID=et.DriID AND ss.SStatusID !=9),et.IgStatus)
in (Select val from Split('A,B,C,D,E',',')))
)
getfilstatus status contains the following code:-
if (#ServerDatetime <= DATEADD(MI,-10, GETDATE()))
BEGIN
IF(#xIgStatus = 'ON')
BEGIN
set #FilStatus= 'NoSignal'
END
ELSE
BEGIN
set #FilStatus= 'Stopped'
end
End
else IF(#xIgStatus = 'ON')
Begin
if(#Speed>5)
begin
if(#JCount<=0)
set #FilStatus='Moving'
else
set #FilStatus='Working'
end
else
begin
set #FilStatus= 'Idle'
end
End
else
Begin
set #FilStatus= 'Stopped'
end
RETURN #FilStatus
GetFilStatus always returns more than 10000 records. Sometimes its more than 100000. Its slowing the final output of query. Currently its taking more than 2 mins to return the output.
I am searching for any other option or any other trick using which the query performance can be increased and I could get the output in seconds.
Any suggestions? Any ideas?
It is better to put the split items in a temp table, as the split function needs to execute each time in the query iterations.
The third parameter has a complex inline query, i have created a temp table for the subset data and filtered necessary data inline.
SELECT S.items AS value
INTO #splited_items
FROM Split('A,B,C,D,E', ',') S;
SELECT Count(J.jid) AS Count_JId,
JN.driid AS DriID
INTO #joined_table
FROM tbl_nt J
INNER JOIN tbl_nassign JN
ON JN.nno = J.nno
INNER JOIN dbo.tbl_cstatus JS
ON JS.cstatusid = J.cstatusid
INNER JOIN dbo.tbl_sstatus ss
ON ss.sstatusid = JS.sstatusid
WHERE ss.sstatusid != 9
GROUP BY JN.driid
SELECT col1,
col2,
col3... from table1
WHERE ( dbo.Getfilstatus(et.sgdate, et.speed, (SELECT count_jid
FROM #joined_table
WHERE driid = et.driid),
et.igstatus)
IN (SELECT value
FROM #splited_items) )

SQL Server:An expression of non-boolean type specified in a context where a condition is expected

I apologize I'm asking this question when this specific error type has already been asked multiple times before, but I've looked through them and am not explicitly seeing my answer.
I am trying to build a trigger that takes records inserted into a table (FDC_Trip_History), selects some information from the record, joins on other tables to pull additional data, etc. and inserts a record into another table (Staging).
I'm getting this error at the bottom of my script, the 4th line from the end after the FROM section. Any idea why?
CREATE TRIGGER Insert_Trip_History ON FDC_Trip_History
AFTER INSERT
AS BEGIN
SET NOCOUNT ON;
--If inserted record reaches a certain 'status' of archive then continue
If EXISTS (SELECT * FROM inserted WHERE inserted.description like '%archive%')
BEGIN
--If inserted record can be 'billed', and hasn't already been processed, then continue.
IF EXISTS ( SELECT * FROM inserted
INNER JOIN FDC_Trips on inserted.tdate = FDC_Trips.tdate and inserted.job = FDC_Trips.job and inserted.SourceDB = FDC_trips.sourceDB
INNER JOIN AMS.dbo.Billable_Outcome_Filter as eBill on FDC_trips.SourceDB = eBill.SourceDB and FDC_Trips.outcome = eBill.Outcome_Code)
AND NOT EXISTS ( SELECT * FROM inserted
INNER JOIN Staging as Stg on inserted.tdate = Stg.tdate and inserted.job = Stg.job and inserted.sourcedb = Stg.sourceDB)
BEGIN
INSERT INTO Staging
(EVENT_OPERATION,
EVENT_SOURCE_TABLE,
EVENT_PRIORITY,
EVENT_TIME_UPDATED,
EVENT_STATUS,
EVENT_COMMENT,
TDATE,
JOB,
SOURCEDB,
CUSTNO,
SHIFTNO,
TYPE,
PROFITCENTER,
BILLINGRATEPROFITCENTER)
SELECT
'CREATE' as [EVENT_OPERATION],
'FDC_Trip_History' as [EVENT_SOURCE_TABLE],
'1' as [EVENT_PRIORITY],
GETDATE() as [EVENT_TIME_ADDED],
null as [EVENT_TIME_UPDATED],
'0' as [EVENT_STATUS],
'' as [EVENT_COMMENT],
eTHistory.tdate as [TDATE],
eTHistory.job as [JOB],
eTHistory.sourcedb as [SOURCEDB],
eT.custno as [CUSTNO],
eT.shiftno as [SHIFTNO],
'Completed' as [TYPE],
--Decide Profit Center. Profit center (PC) determined from dispatch zone (Trips.dzone)
CASE
WHEN cType.descr LIKE 'ATS%'
THEN DispatchZone.ATS_ProfitCenter
ELSE DispatchZone.ProfitCenter
END,
--Decide Billing rate profit center. Billing rate profit center (BRPC) determined from pickup zone. Does ATS logic apply to BRPC too?
CASE
WHEN cType.descr LIKE 'ATS%'
THEN PickupZone.ATS_ProfitCenter
ELSE PickupZone.ProfitCenter
END
as [BILLINGRATEPROFITCENTER]
FROM inserted
INNER JOIN FDC_Trip_History as eTHistory
INNER JOIN FDC_Trips as eT on eTHistory.tdate = eT.tdate and eTHistory.job = eT.job and eTHistory.sourcedb = eT.sourcedb
LEFT JOIN Trips as T on T.tdate = eTHistory.tdate and T.sourcedb = eTHistory.sourceDB and T.Job = eTHistory.Job
LEFT JOIN Call_Types as cType on cType.code = eT.calltype and cType.sourceDB = eT.sourceDB
LEFT JOIN Zones as DispatchZone on DispatchZone.code = T.dzone
LEFT JOIN Zones as PickupZone on PickupZone.code = eT.puzone /* Error pops up right here */
END
END
END
You seem to have forgotton the specify the join criteria for the FDC_Trip_History table (the first INNER JOIN).
In addition, you have 14 columns in your INSERT list but 15 in your SELECT statement.

sql server update from select

Following the answer from this post, I have something like this:
update MyTable
set column1 = otherTable.SomeColumn,
column2 = otherTable.SomeOtherColumn
from MyTable
inner join
(select *some complex query here*) as otherTable
on MyTable.key_field = otherTable.key_field;
However, I keep getting this error:
The column prefix 'otherTable' does
not match with a table name or alias
name used in the query.
I'm not sure what's wrong. Can't I do such an update from a select query like this?
Any help would be greatly appreciated.
(I'm using *blush* sql server 2000.)
EDIT:
here's the actual query
update pdx_projects set pr_rpc_slr_amount_year_to_date = summary.SumSLR, pr_rpc_hours_year_to_date = summary.SumHours
from pdx_projects pr join (
select pr.pr_pk pr_pk, sum(tc.stc_slr_amount) SumSLR, sum(tc.stc_worked_hours) SumHours from pdx_time_and_cost_from_rpc tc
join pdx_rpc_projects sp on tc.stc_rpc_project_id = sp.sol_rpc_number
join pdx_rpc_links sl on sl.sol_fk = sp.sol_pk
join pdx_projects pr on pr_pk = sl.pr_fk
where tc.stc_time_card_year = year(getdate())
group by pr_pk
) as summary
on pr.pr_pk = summary.pr_pk
and the actual error message is
Server: Msg 107, Level 16, State 2,
Line 1 The column prefix 'summary'
does not match with a table name or
alias name used in the query.
I submit to you this altered query:
update x
set x.pr_rpc_slr_amount_year_to_date = summary.sumSLR,
x.pr_rpc_hours_year_to_date = summary.sumHours
from pdx_projects x
join (
select pr.pr_pk as pr_pk,
sum(tc.stc_slr_amount) as SumSLR,
sum(tc.stc_worked_hours) as SumHours
from pdx_time_and_cost_from_rpc tc
join pdx_rpc_projects sp on tc.stc_rpc_project_id = sp.sol_rpc_number
join pdx_rpc_links sl on sp.sol_pk = sl.sol_fk
join pdx_projects pr on sl.pr_fk = pr.pr_pk
where tc.stc_time_card_year = year(getdate())
group by pr.pr_pk
) as summary
on x.pr_pk = summary.pr_pk
Notably different here: I don't re-use the alias pr inside and outside of the complex query. I re-ordered the joins the way I like them (previously referenced table first,) and explicitly notated pr_pk in 2 places. I also changed the update syntax to use update <alias>.
Maybe not the answer you're looking for, but instead of generating hugely complex queries, I usually default to inserting the some complex query here into a table variable. Then you can do a simple update to MyTable with a join to the table variable. It may not be quite as efficient, but its much easier to maintain.
I couldn't replicate your error using SQL 2008 in 80 compatibility level. While this option doesn't guarantee that I'll get the same results as you, nothing appears to be out of place.
create table pdx_projects
(
pr_rpc_slr_amount_year_to_date varchar(max)
, pr_rpc_hours_year_to_date varchar(max)
, pr_pk varchar(max)
)
create table pdx_time_and_cost_from_rpc
(
stc_slr_amount decimal
, stc_worked_hours decimal
, stc_rpc_project_id varchar(max)
, stc_time_card_year varchar(max)
)
create table pdx_rpc_projects
(
sol_rpc_number varchar(max)
, sol_pk varchar(max)
)
create table pdx_rpc_links
(
sol_fk varchar(max)
, pr_fk varchar(max)
)
update pdx_projects
set
pr_rpc_slr_amount_year_to_date = summary.SumSLR
, pr_rpc_hours_year_to_date = summary.SumHours
from
pdx_projects pr
join (
select pr.pr_pk pr_pk
, sum(tc.stc_slr_amount) SumSLR
, sum(tc.stc_worked_hours) SumHours
from pdx_time_and_cost_from_rpc tc
join pdx_rpc_projects sp on tc.stc_rpc_project_id = sp.sol_rpc_number
join pdx_rpc_links sl on sl.sol_fk = sp.sol_pk
join pdx_projects pr on pr_pk = sl.pr_fk
where tc.stc_time_card_year = year(getdate())
group by pr_pk
) as summary
on pr.pr_pk = summary.pr_pk