Need to replace #temp tables with CTE

  • Hi,

    I've been asked to adjust my query by using CTE instead of #temp tables as it is slowing down the entire network.

    The reason I used #temp tables was to break down my query into simple an understandable parts for anyone reading my query.

    I create the first #temp table and then select into the second one. I then drop the first one. I will then Select everything in the second one as well as additional columns into a third #temp table and then drop the second one and so on. I have about 30 #temp tables.

    Here is an example of 3 of them I have. I'm hoping for a simple way to use CTE to join these 4 and then the remaining 27 or so.

    Thanks!

    Select

    al.ProductLine

    ,al.PaymentFrequency

    ,al.PolicyVersionID

    ,al.PolicyID

    ,al.FirstStartDate

    ,al.NameID

    ,(1-((1-(ISNULL(al.DiscountPercent,0)/100))*(1-(ISNULL(al.AdditionalDiscountForRenewalAdjustments,0)/100)))) Discount

    ,ccx.NameID

    ,ccx.ClaCaseID

    ,ccx.ClaEventID

    ,ObjectVersionID

    ,ccx.PolicyLineVersionID

    ,ccx.PolicyLineID

    into #InitialTable_1

    from Staging.ClaCases ccx

    LEFT JOIN Staging.PolicyLines al

    ON ccx.PolicyLineVersionID = al.PolicyLineVersionID

    where ProductLine = 'WHEEL'

    --***************************************************************************************

    Select it.*

    ,ce.IncidentDate

    ,ce.EventType

    ,ce.SubPlaceID Incident_SubPlaceID

    ,ce.DayAddrCode

    ,ce.RiskAddrCode

    into #InitialTable_2

    from #InitialTable_1 it

    LEFT JOIN Staging.ClaEvents ce

    ON it.ClaEventID = ce.ClaEventID

    GO

    Drop Table #InitialTable_1

    GO

    --***************************************************************************************

    Select it.*

    ,ISNULL((select z.Previous_claims

    from

    (

    select ca.NameID

    ,ce.IncidentDate

    ,ca.ClaCaseID

    ,(

    select count(*)

    from Staging.ClaCases ca2

    , Staging.ClaEvents ce2

    where ca2.ClaEventID = ce2.ClaEventID

    and ca2.NameID = ca.NameID

    and ce2.IncidentDate < ce.IncidentDate

    ) as Previous_claims

    from Staging.ClaCases ca

    , Staging.ClaEvents ce

    where ca.ClaEventID = ce.ClaEventID

    ) z

    where z.ClaCaseID = it.ClaCaseID),0) Previous_claims

    into #InitialTable_3

    from #InitialTable_2 it

    GO

    Drop Table #InitialTable_2

    GO

    --***************************************************************************************

    ;WITH CTE AS (

    SELECT ITCScoreDate, NameID, ITCScore,

    ROW_NUMBER() OVER (PARTITION BY NameID ORDER BY CASE WHEN ITCScore IS NULL

    THEN ITCScoreDate

    ELSE GETDATE() END DESC) AS rn

    from Staging.ITCChecks)

    SELECT it.*, ITCScore

    into #InitialTable_4

    from #InitialTable_3 it

    LEFT JOIN (

    SELECT ITCScoreDate, NameID, ITCScore

    from CTE

    where rn = 1

    ) cteJoin

    ON it.NameID = cteJoin.NameID

    GO

    Drop Table #InitialTable_3

    --***************************************************************************************

    Alter Table #InitialTable_4

    ADD

    Distance_to_work varchar(100)

    GO

    MERGE into #InitialTable_4 dst --into clause to specify the target table

    USING ( --USING clause to specify the source of the data to be updated or inserted

    SELECT ff.ObjectVersionID --Subquery

    , MIN(ISNULL( (d.CentreX),0)) AS day_x

    , MIN(ISNULL( (d.CentreY),0)) AS day_y

    , MIN(ISNULL( (n.CentreX),0)) AS night_x

    , MIN(ISNULL( (n.CentreY),0)) AS night_y

    from #InitialTable_4 ff

    LEFT JOIN Geo.GISAreas d ON ff.DayAddrCode = d.SubplaceID --ON clause to specify the condition upon which the MERGE operation either updates or inserts

    LEFT JOIN Geo.GISAreas n ON ff.RiskAddrCode = n.SubplaceID

    GROUP BY ff.ObjectVersionID

    ) src

    ON (src.ObjectVersionID = dst.ObjectVersionID)

    WHEN MATCHED THEN

    UPDATE SET dst.Distance_to_work = 100 * SQRT ( POWER (src.day_x - src.night_x, 2)

    + POWER (src.day_y - src.night_y, 2)

    );

    GO

  • I can't work out what your question is here. The way to use multiple CTEs is like this:

    WITH CTE1 AS (

    SELECT...

    FROM...

    WHERE...

    ), CTE2 AS (

    SELECT...

    FROM...

    WHERE...

    )

    <Now use your CTEs here the same way you would use temp tables>

    I notice that you said you'd been asked to change to CTEs. You will want to do comprehensive testing to make sure that doing so actually produces an improvement.

    John

  • I'd be surprised if it makes an improvement.

    Without DDL, sample data and expected results, all I'm going to do is directly convert your temp tables into CTEs. If you want a better answer, read the link in my sig and post DDL with readily consumable sample data and expected results.

    WITH InitialTable_1

    AS (

    SELECT al.ProductLine, al.PaymentFrequency, al.PolicyVersionID, al.PolicyID, al.FirstStartDate, al.NameID, (1 - ((1 - (ISNULL(al.DiscountPercent, 0) / 100)) * (1 - (ISNULL(al.AdditionalDiscountForRenewalAdjustments, 0) / 100)))) Discount, ccx.NameID, ccx.ClaCaseID, ccx.ClaEventID, ObjectVersionID, ccx.PolicyLineVersionID, ccx.PolicyLineID

    FROM Staging.ClaCases ccx

    LEFT JOIN Staging.PolicyLines al ON ccx.PolicyLineVersionID = al.PolicyLineVersionID

    WHERE ProductLine = 'WHEEL'

    ), InitialTable_2

    AS (

    SELECT it.*, ce.IncidentDate, ce.EventType, ce.SubPlaceID Incident_SubPlaceID, ce.DayAddrCode, ce.RiskAddrCode

    FROM InitialTable_1 it

    LEFT JOIN Staging.ClaEvents ce ON it.ClaEventID = ce.ClaEventID

    ), InitialTable_3

    AS (

    SELECT it.*, ISNULL((

    SELECT z.Previous_claims

    FROM (

    SELECT ca.NameID, ce.IncidentDate, ca.ClaCaseID, (

    SELECT count(*)

    FROM Staging.ClaCases ca2, Staging.ClaEvents ce2

    WHERE ca2.ClaEventID = ce2.ClaEventID

    AND ca2.NameID = ca.NameID

    AND ce2.IncidentDate < ce.IncidentDate

    ) AS Previous_claims

    FROM Staging.ClaCases ca, Staging.ClaEvents ce

    WHERE ca.ClaEventID = ce.ClaEventID

    ) z

    WHERE z.ClaCaseID = it.ClaCaseID

    ), 0) Previous_claims

    FROM InitialTable_2 it

    ), CTE

    AS (

    SELECT ITCScoreDate, NameID, ITCScore, ROW_NUMBER() OVER (

    PARTITION BY NameID ORDER BY CASE

    WHEN ITCScore IS NULL

    THEN ITCScoreDate

    ELSE GETDATE()

    END DESC

    ) AS rn

    FROM Staging.ITCChecks

    )

    SELECT it.*, ITCScore

    INTO #InitialTable_4

    FROM InitialTable_3 it

    LEFT JOIN (

    SELECT ITCScoreDate, NameID, ITCScore

    FROM CTE

    WHERE rn = 1

    ) cteJoin ON it.NameID = cteJoin.NameID

    GO

    ALTER TABLE #InitialTable_4 ADD Distance_to_work VARCHAR(100)

    GO

    MERGE INTO #InitialTable_4 dst --into clause to specify the target table

    USING (

    --USING clause to specify the source of the data to be updated or inserted

    SELECT ff.ObjectVersionID --Subquery

    , MIN(ISNULL((d.CentreX), 0)) AS day_x, MIN(ISNULL((d.CentreY), 0)) AS day_y, MIN(ISNULL((n.CentreX), 0)) AS night_x, MIN(ISNULL((n.CentreY), 0)) AS night_y

    FROM #InitialTable_4 ff

    LEFT JOIN Geo.GISAreas d ON ff.DayAddrCode = d.SubplaceID --ON clause to specify the condition upon which the MERGE operation either updates or inserts

    LEFT JOIN Geo.GISAreas n ON ff.RiskAddrCode = n.SubplaceID

    GROUP BY ff.ObjectVersionID

    ) src

    ON (src.ObjectVersionID = dst.ObjectVersionID)

    WHEN MATCHED

    THEN

    UPDATE

    SET dst.Distance_to_work = 100 * SQRT(POWER(src.day_x - src.night_x, 2) + POWER(src.day_y - src.night_y, 2));

    GO


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • mic.con87 (2/10/2012)


    Hi,

    I've been asked to adjust my query by using CTE instead of #temp tables as it is slowing down the entire network.

    ...

    I have a question.

    Why are temp tables slowing down the network?

  • Thanks for the post Cadavre, that answers my question. I'll read up on what you posted

  • Jcb im no expert but I was told that even though I drop the temp tables they sit in a TempDB and the drive that they sit on is almost at full capacity. Something about it being stored in memory or a cache, I'm really no expert.

  • When you create temp tables it lies in the tempdb.

    When you drop temp tables or closes the connection they are erased from tempdb.

    When you query needs to create "behind the scenes" datasets it uses memory/tempdb.

    I cannot figures yet temp tables impact in network.

Viewing 7 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic. Login to reply