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.