Hi Guys,
I have managed to make some headway with the long running query. In the first instance I took the advice J Livingston and indexed the source tables. With this the original query dropped from 25mins to 4min 50sec.
I rewrote the script along the lines suggested by Jeff and the query ran in 3min 30 secs. I had to make a few adjustments to the Stuff statements as I checked again with the consumer of the data to find out what actually needed to be concatenated.
The final script was as follows:
WITH ctePreAggPstProdTmpl
AS
(
SELECT TemplateID
, SpecID --To be used as a join filter in another query.
, SpecIDs =
STUFF(
(
SELECT ' ; ' + Data FOR XML PATH('')),1,3,'')
FROM dbo.PstProdTmplData
WHERE SpecID IN
(
'Episode title'
,'Commercial brand'
,'Commercial product'
,'Commercial type'
,'Country of origin'
,'Year of production'
)
AND TemplateID IN (SELECT ItemID FROM dbo.InventTable) --Implicitly DISTINCT and as fast as a join.
GROUP BY TemplateID, SpecID,Data
)
--Pivot Aggregate Data
SELECT TemplateID = ISNULL(TemplateID,0) --Makes the column in the lookup table NOT NULL.
, CREpisodeTitle = MAX(CASE WHEN SpecID = 'Episode title' THEN SpecIDs ELSE '' END)
, CRComBrand = MAX(CASE WHEN SpecID = 'Commercial brand' THEN SpecIDs ELSE '' END)
, CRComProduct = MAX(CASE WHEN SpecID = 'Commercial product' THEN SpecIDs ELSE '' END)
, CRComType = MAX(CASE WHEN SpecID = 'Commercial type' THEN SpecIDs ELSE '' END)
, CRCountry = MAX(CASE WHEN SpecID = 'Country of origin' THEN SpecIDs ELSE '' END)
, CRYear = MAX(CASE WHEN SpecID = 'Year of production' THEN SpecIDs ELSE '' END)
INTO #Lookup_PstProdTmplData
FROM ctePreAggPstProdTmpl
GROUP BY TemplateID
ALTER TABLE #Lookup_PstProdTmplData
ADD PRIMARY KEY CLUSTERED (TemplateID)
;
-- CREATE CRAltNumber Lookup
SELECT N1.[CREATIONID],
STUFF
((SELECT ' ; ' + N2.CRNUMBERTYPEID + '|#|' + N2.CRNUMBER + CASE N2.CRSOCIETYCODE WHEN '0' THEN '' ELSE '|#|' + N2.CRSOCIETYCODE END
FROM CRALTNUMBERS N2
WHERE N1.CREATIONID = N2.CREATIONID FOR XML PATH('')), 1, 3, '') AS CRNumbers
INTO #Lookup_CRALTNUMBERS
FROM CRALTNUMBERS N1 WHERE N1.[CREATIONID] IN (SELECT ItemID FROM dbo.InventTable)
GROUP BY N1.[CREATIONID]
ALTER TABLE #Lookup_CRALTNUMBERS
ADD PRIMARY KEY CLUSTERED (CREATIONID)
-- CREATE CRTITLE Lookup
SELECT N1.[CREATIONID],
STUFF
((SELECT ' ; ' + N2.CRTITLE
FROM [dbo].[CRALTTITLES] N2
WHERE N1.CREATIONID = N2.CREATIONID FOR XML PATH('')), 1, 3, '') AS CRTitles
INTO #Lookup_CRALTitles
FROM [CRALTTITLES] N1 WHERE N1.[CREATIONID] IN (SELECT ItemID FROM dbo.InventTable)
GROUP BY N1.[CREATIONID]
ALTER TABLE #Lookup_CRALTitles
ADD PRIMARY KEY CLUSTERED (CREATIONID)
-- CREATE MATCHNAME Lookup
SELECT N1.[CREATIONID],
STUFF
((SELECT ' ; ' + LTRIM(N2.FIRSTNAME + ' ' + N2.NAME)
FROM [dbo].[MATCHNAME] N2
WHERE N1.CREATIONID = N2.CREATIONID FOR XML PATH('')), 1, 3, '') AS CRNames
INTO #Lookup_MatchNames
FROM [CRALTTITLES] N1 WHERE N1.[CREATIONID] IN (SELECT ItemID FROM dbo.InventTable)
GROUP BY N1.[CREATIONID]
ALTER TABLE #Lookup_MatchNames
ADD PRIMARY KEY CLUSTERED (CREATIONID)
-- CREATE BOM Parents Lookup
SELECT b1.[ITEMID],
STUFF
((SELECT ' ; ' + b2.BOMID
FROM BOM b2
WHERE b1.ITEMID = b2.ITEMID FOR XML PATH('')), 1, 3, '') AS CRParents
INTO #Lookup_BOMParents
FROM [dbo].[BOM] b1 WHERE b1.ITEMID IN (SELECT ItemID FROM dbo.InventTable)
GROUP BY b1.[ITEMID]
ALTER TABLE #Lookup_BOMParents
ADD PRIMARY KEY CLUSTERED (ITEMID)
--CREATE BOM Children Lookup
SELECT b1.BOMID,
STUFF
((SELECT ' ; ' + b2.ItemID
FROM BOM b2
WHERE b1.BOMID = b2.ITEMID FOR XML PATH('')), 1, 3, '') AS CRChildren
INTO #Lookup_BOMChildren
FROM [dbo].[BOM] b1 WHERE b1.BOMID IN (SELECT ItemID FROM dbo.InventTable)
GROUP BY b1.BOMID
ALTER TABLE #Lookup_BOMChildren
ADD PRIMARY KEY CLUSTERED (BOMID)
SELECT i.ITEMID AS CRItemID, i.PSTPRODUCTID AS CRProductID, i.NAMEALIAS AS CRName, i.CREATIONPERFORMER AS CRPerformer,
i.CREATIONDURATION AS CRDuration, i.CREATIONSTATUS AS CRStatus, i.[MODIFIEDDATETIME] AS CRModifiedDateTime,
c.CRNumbers, T.CRTitles, M.CRNames, B.CRParents, W.CRChildren, P.CREpisodeTitle, p.CRComBrand, p.CRComProduct, p.CRComType, p.CRCountry, p.CRYear
FROM dbo.InventTable i
LEFT JOIN #Lookup_PstProdTmplData p
ON p.TemplateID = i.ItemID
LEFT JOIN #Lookup_CRALTNUMBERS C
ON C.CREATIONID = i.ItemID
LEFT JOIN #Lookup_MatchNames M
ON M.CreationID = I.ItemID
LEFT JOIN #Lookup_CRALTitles T
ON T.CREATIONID = i.ItemID
LEFT JOIN #Lookup_BOMParents B
ON B.ITEMID = i.ItemID
LEFT JOIN #Lookup_BOMChildren W
ON W.BOMID = I.ITEMID
I will follow the advice of J Livingston and run within SSIS with separate SQL Tasks for each stuff component. Anymore increased performance will be a further bonus. Many thanks for the help and tips. Really helped change my mindset with this query. The comments about naming conventions have been taken on board 😉