简体   繁体   中英

Updating rows in table with group of data from the same table

I have this table below:

Indicator  Year         Month     FirstDayPeriod      NrOfThings   NmbrOfThingsPastYear
99         2013         1         Jan  1 2013         10858         
99         2013         2         Feb  1 2013         8264         
99         2013         3         Mar  1 2013         9716         
99         2013         4         Apr  1 2013         8549         
99         2013         5         May  1 2013         8144         
99         2013         6         Jun  1 2013         7917         
99         2013         7         Jul  1 2013         9585         
99         2013         8         Aug  1 2013         7426         
99         2013         9         Sep  1 2013         7877         
99         2013         10        Oct  1 2013         9707         
99         2013         11        Nov  1 2013         8925         
99         2013         12        Dec  1 2013         13709         
99         2014         1         Jan  1 2014         11183         
99         2014         2         Feb  1 2014         8518         
99         2014         3         Mar  1 2014         10545         
99         2014         4         Apr  1 2014         9582         
99         2014         5         May  1 2014         10278         
99         2014         6         Jun  1 2014         9330         
99         2014         7         Jul  1 2014         11366         
99         2014         8         Aug  1 2014         9161         
99         2014         9         Sep  1 2014         10651         
99         2014         10        Oct  1 2014         11331         
99         2014         11        Nov  1 2014         10624         126278
99         2014         12        Dec  1 2014         17958         130527
99         2015         1         Jan  1 2015         11431         130775

The last column ( NmbrOfThingsPastYear ) is to be the total of NrOfThings for the past 12 months. So the NmbrOfThingsPastYear for Nov 2014 is defined by the sum of NrOfThings for nov 2014, oct 2014, sep 2014, etc... uptil dec 2013... What I would like to do is updating the column NmbrOfThingsPastYear in this table with the values in this table...

This statement provides the correct values for just november 2014:

SELECT 
Indicator,
MAX(tsum.FirstDayPeriod),
SUM(tsum.AantalTaken)
FROM tempdb..TableAbove tsum 
WHERE tsum.FirstDayPeriod > dateadd(mm, -12, '20141101') 
  AND tsum.FirstDayPeriod <= '20141101'
GROUP BY 
Indicator

So I'm looking for a construction where I can update the column NmbrOfThingsPastYear in every row in the table with the values (The sum of the NrOfThings for the preceeding 12 months) for each month..

Can anybody help me? Thx in advance!

I have achieved what you are after but using a cursor. If anyone converts this or post set based logic then go with that.

I have created a temp table called #stuff in order to replicate what you are trying to do. As you can see each FirstDayPeriod date is looped and then the previous 12 months NrOfThings are summed. NrOfthingsPastYear is then updated based on the FirstDayPeriod. You can increase the scope easily here for such things as the indicator, but the below should give you a base:

IF OBJECT_ID('tempdb..#Stuff') IS NOT NULL DROP TABLE #Stuff

GO

CREATE TABLE #Stuff
(Indicator int, 
FirstDayPeriod datetime,
NrOfthings int,
NrOfthingspastyear int)

INSERT INTO #Stuff ( Indicator, FirstDayPeriod, NrOfthings, NrOfThingsPastYear)

VALUES (99, 'Jan 1 2013', '32432', 0),
 (99, 'Feb 1 2013', '322', 0),
 (99, 'Mar 1 2013', '312', 0),
 (99, 'Apr 1 2013', '32432', 0),
 (99, 'May 1 2013', '32', 0),
 (99, 'Jun 1 2013', '32432', 0),
 (99, 'Jul 1 2013', '32432', 0),
 (99, 'Aug 1 2013', '32092', 0),
 (99, 'Sep 1 2013', '2', 0),
 (99, 'Oct 1 2013', '32432', 0),
 (99, 'Nov 1 2013', '32432', 0),
 (99, 'Dec 1 2013', '312', 0),
 (99, 'Jan 1 2014', '32232', 0),
 (99, 'Feb 1 2014', '32432', 0),
 (99, 'Mar 1 2014', '32432', 0),
 (99, 'Apr 1 2014', '3932', 0),
 (99, 'May 1 2014', '3242', 0),
 (99, 'Jun 1 2014', '32432', 0),
 (99, 'Jul 1 2014', '324', 0),
 (99, 'Aug 1 2014', '32432', 0),
 (99, 'Sep 1 2014', '3532', 0),
 (99, 'Oct 1 2014', '32432', 0),
 (99, 'Nov 1 2014', '332', 0),
 (99, 'Dec 1 2014', '3232', 0)


DECLARE @FirstDayPeriod datetime

DECLARE crs1 CURSOR 

FOR

SELECT
    FirstDayPeriod
FROM #Stuff

OPEN crs1
FETCH NEXT FROM Crs1 Into @FirstDayPeriod

WHILE @@FETCH_STATUS = 0

BEGIN

    UPDATE 
        #Stuff
    SET
        NrOfThingsPastYear =( 
                            SELECT
                                SUM(nrOfThings)
                            FROM
                                #Stuff
                            WHERE FirstDayPeriod > dateadd(mm, -12, @FirstDayPeriod) 
                              AND FirstDayPeriod <= @FirstDayPeriod
                            )
    WHERE
        FirstDayPeriod = @FirstDayPeriod

FETCH NEXT FROM crs1 INTO @FirstDayPeriod

END

CLOSE crs1
DEALLOCATE crs1

SELECT * FROM #Stuff

It's just a matter of joining and grouping. The query should be relatively self-explanatory. Just take each row of the table and join with itself and the preceding 11 months. Then group on the date of that row (there should be 12 of them) and add the joined values.

SELECT  tsum1.Indicator, tsum1.FirstDayPeriod, 
        Sum( tsum2.NrOfThings ) NmbrOfThingsPastYear
FROM    TableAbove tsum1
join    TableAbove tsum2
    on  tsum2.Indicator = tsum1.Indicator
    and tsum2.FirstDayPeriod -- between now and a year ago
        between DateAdd( Month, -11, tsum1.FirstDayPeriod )
            and tsum1.FirstDayPeriod
group BY tsum1.Indicator, tsum1.FirstDayPeriod -- gather into 12-month chunks
having count(*) > 11 -- leave out any chunks of less than 12 months
order by tsum1.Indicator, tsum1.FirstDayPeriod;

The having clause prevents partial results but you can omit it if you want.

Turning this into an update statement will be a little tricky because of the grouping. If nothing else, just feed this result set back into a join with the table and use that.

Here is the Fiddle . It uses SQL Server as SQLFiddle doesn't have Sybase, but it will be close.

I guess I should install Sybase at home...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM