SUM relative to row date value

  • Yes, thanks. For this test data

    SELECT 'Small House', 'A', 2010/02/01', 10, 100 UNION ALL

    SELECT 'Big House', 'B','2010/06/01', 2, 200 UNION ALL

    SELECT 'Big House', 'A','2010/06/01', 20, 2000 UNION ALL

    SELECT 'Small House', 'A','2010/04/01', 4, 40 UNION ALL

    SELECT 'Small House', 'A','2010/01/01', 30, 300

    I'd like to see the new metrics (derived from those running totals) setting purposely 0 metrics in @TABLE. So we'd use the below for an update script joining on a.location = b.location, a.grade = b.grade and a.yearmonth = b.yearmonth

    Location, Grade, Yearmonth, Aggregate1, Aggregate3

    'Small House', 'A', 2010/02/01', 40, 400

    'Big House', 'B','2010/06/01', 2, 200

    'Big House', 'A','2010/06/01', 20, 2000

    'Small House', 'A','2010/04/01', 14, 50

    'Small House', 'A','2010/01/01', 30, 300

    I think that is it !

    Regards, Greg.

  • Hmmm, not sure that I understand correctly.

    (Sorry if I'm a bit slow replying, got a lovely issue that I'm solving at work)

    Currently, the code I've supplied would show the following if executed against your new test data: -

    Location Grade Yearmonth Metric1 Metric2 Metric3 Metric4

    -------------------------------------------------- -------------------------------------------------- ----------------------- ----------- ----------- ----------- -----------

    Small House A 2010-01-01 00:00:00.000 30 30 300 300

    Small House A 2010-02-01 00:00:00.000 10 40 100 400

    Small House A 2010-04-01 00:00:00.000 4 14 40 140

    Big House B 2010-06-01 00:00:00.000 2 28 200 2440

    Big House A 2010-06-01 00:00:00.000 20 28 2000 2440


    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/

  • Cadavre (8/31/2011)


    greg.bull (8/31/2011)


    On to the next point, if a month row is missing, then it'd be ignored, so for month 6, we'd be summing month 6, month 5 (which'd be null) and month 4. We wouldn't want to find another month going back a bit more with non null data.

    Ah, well this needs cleaning up but it gets the result you're after. I'm sure someone will make a much more efficient version πŸ™‚

    --First, lets build some test data

    DECLARE @TABLE AS TABLE (Yearmonth DATETIME, Metric1 INT, Metric2 INT)

    INSERT INTO @TABLE (Yearmonth, Metric1)

    SELECT '2010/01/01', 1 UNION ALL

    SELECT '2010/02/01', 2 UNION ALL

    SELECT '2010/03/01', 3 UNION ALL

    SELECT '2010/04/01', 4 UNION ALL

    SELECT '2010/06/01', 5

    --Tally table would be better, for testing purposes I've included one here "on the fly"

    ;WITH t1 AS (SELECT 1 N UNION ALL SELECT 1 N),

    t2 AS (SELECT 1 N FROM t1 x, t1 y),

    t3 AS (SELECT 1 N FROM t2 x, t2 y),

    t4 AS (SELECT 1 N FROM t3 x, t3 y),

    tally AS (SELECT DATEADD(MONTH,ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1,0) AS thedate

    FROM t4 x, t4 y)

    --Actual code -> It's a god-awful mess, and could do with some optimising but gets the correct result

    UPDATE t2

    SET Metric2 = ISNULL(RunningTotal,0)

    FROM @TABLE t2

    LEFT OUTER JOIN (SELECT a.Yearmonth, ISNULL(b.Metric1,0) AS Metric1

    FROM (SELECT thedate AS Yearmonth

    FROM (SELECT MIN(Yearmonth) minYearMonth, MAX(Yearmonth) maxYearMonth

    FROM @TABLE) a

    CROSS APPLY tally

    WHERE minYearMonth <= thedate AND maxYearMonth >= thedate) a

    LEFT OUTER JOIN @TABLE b ON a.Yearmonth = b.Yearmonth) t1 ON t1.Yearmonth = t2.Yearmonth

    LEFT OUTER JOIN (SELECT Yearmonth, SUM(Metric1) AS RunningTotal

    FROM (SELECT A.Yearmonth AS Yearmonth, B.Yearmonth AS Yearmonth_B,

    B.Metric1

    FROM (SELECT Yearmonth, Metric1, ROW_NUMBER() OVER(ORDER BY YearMonth) AS ID

    FROM (SELECT a.Yearmonth, ISNULL(b.Metric1,0) AS Metric1

    FROM (SELECT thedate AS Yearmonth

    FROM (SELECT MIN(Yearmonth) minYearMonth, MAX(Yearmonth) maxYearMonth

    FROM @TABLE) a

    CROSS APPLY tally

    WHERE minYearMonth <= thedate AND maxYearMonth >= thedate) a

    LEFT OUTER JOIN @TABLE b ON a.Yearmonth = b.Yearmonth) a) A

    CROSS JOIN (SELECT Yearmonth, Metric1, ROW_NUMBER() OVER(ORDER BY YearMonth) AS ID

    FROM (SELECT a.Yearmonth, ISNULL(b.Metric1,0) AS Metric1

    FROM (SELECT thedate AS Yearmonth

    FROM (SELECT MIN(Yearmonth) minYearMonth, MAX(Yearmonth) maxYearMonth

    FROM @TABLE) a

    CROSS APPLY tally

    WHERE minYearMonth <= thedate AND maxYearMonth >= thedate) a

    LEFT OUTER JOIN @TABLE b ON a.Yearmonth = b.Yearmonth) a) B

    WHERE (B.ID >= A.ID-2 AND B.ID <= A.ID) ) T

    GROUP BY Yearmonth) tot ON t1.Yearmonth=tot.Yearmonth

    WHERE t1.Yearmonth = t2.Yearmonth

    SELECT * FROM @TABLE

    --EDIT--

    ChrisM@Work (8/31/2011)


    UPDATE #Sample SET Metric2 = ISNULL(NULLIF(Metric1+Metric1-1+Metric1-2,0),1)

    πŸ˜‰

    LOL!! Didn't think of that for the previous requirements. Awesome, will have to remember not to over-complicate things. . . *glances at new version of code*. . . hmmm :hehe:

    Simple is good...

    DROP TABLE #Sample

    CREATE TABLE #Sample (Yearmonth DATE, Metric1 INT, Metric2 INT NULL)

    INSERT INTO #Sample (Yearmonth, Metric1, Metric2)

    SELECT '2010/01/01', 1, NULL UNION ALL

    SELECT '2010/03/01', 3, NULL UNION ALL

    SELECT '2010/02/01', 2, NULL UNION ALL

    SELECT '2010/04/01', 4, NULL UNION all

    SELECT '2010/06/01', 5, NULL

    SELECT s.Yearmonth, s.Metric1, iTVF1.Metric2

    FROM #Sample s

    CROSS APPLY(SELECT Metric2 = SUM(Metric1) FROM #Sample WHERE DATEDIFF(mm,Yearmonth,s.Yearmonth) BETWEEN 0 AND 2) iTVF1

    ORDER BY Yearmonth

    β€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • Nice one Chris πŸ˜‰

    Told you someone would simplify it Greg


    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/

  • Wont this do?

    Shamelessly utilizing the sample data that Cadavre prepared( Thanks Cad)

    DECLARE @TABLE AS TABLE (Yearmonth DATETIME, Metric1 INT, Metric2 INT)

    INSERT INTO @TABLE (Yearmonth, Metric1)

    SELECT '2010/01/01', 1 UNION ALL

    SELECT '2010/02/01', 2 UNION ALL

    SELECT '2010/03/01', 3 UNION ALL

    SELECT '2010/04/01', 4 UNION ALL

    SELECT '2010/05/01', 5

    --== This is added to give the flexibility of changing the number of month you need the Metric2 for

    -- As you initially requested for 3, i have used 3.

    DECLARE @NumberOfMonthsToFindPreviousSum INT

    SET @NumberOfMonthsToFindPreviousSum = 3

    SET @NumberOfMonthsToFindPreviousSum = -1 * @NumberOfMonthsToFindPreviousSum

    SELECT OuterTable.Yearmonth , OuterTable.Metric1 ,CrsAPP.Metric2

    FROM @TABLE OuterTable

    CROSS APPLY

    ( SELECT SUM( InnerTable.Metric1 ) Metric2

    FROM @TABLE InnerTable

    WHERE InnerTable.Yearmonth <= OuterTable.Yearmonth AND

    InnerTable.Yearmonth > DATEADD(MONTH ,@NumberOfMonthsToFindPreviousSum, OuterTable.Yearmonth )

    ) CrsAPP

    ORDER BY OuterTable.Metric1

  • OK thanks chaps, I'll just have a play and try to integrate. Really appreciate your time here.

    Greg

  • Cadavre (8/31/2011)


    Nice one Chris πŸ˜‰

    Told you someone would simplify it Greg

    Wooooosh... i dint see Chris posted a similar solution πŸ˜‰

    { Note to self : Brush the teeth before even reading posts :hehe::hehe: }

  • Cadavre (8/31/2011)


    Nice one Chris πŸ˜‰

    Told you someone would simplify it Greg

    Wonder if it works on the real data though?

    My money's on CC's script, it's more flexible 😎

    β€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • And with proper index on YearMonth column, the script should complete in a jiffy. I wonder if a Quirky Update code can be bestowed on this puzzle :unsure:

  • Chaps,

    Just to let you know, all working properly when integrated into my real database, so thanks for your efforts and you can all feel good about yourselves now ! πŸ™‚

    Regards, Greg.

Viewing 10 posts - 16 through 24 (of 24 total)

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