使用同一 table 中的一组数据更新 table 中的行
Updating rows in table with group of data from the same table
我下面有这个table:
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
最后一列 (NmbrOfThingsPastYear
) 是过去 12 个月 NrOfThings
的总数。因此,2014 年 11 月的 NmbrOfThingsPastYear
由 2014 年 11 月、2014 年 10 月、2014 年 9 月等的 NrOfThings
的总和定义...直到 2013 年 12 月...
我想做的是用 table...
中的值更新 table 中的列 NmbrOfThingsPastYear
此声明提供了 2014 年 11 月的正确值:
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
所以我正在寻找一种结构,我可以在其中使用值更新 table 中每一行的 NmbrOfThingsPastYear
列(前面 NrOfThings
的总和12个月)每个月..
有人可以帮助我吗?
提前致谢!
我已经实现了你想要的,但是使用了游标。如果有人转换这个或 post 基于集合的逻辑,那么就用那个。
我创建了一个名为 #stuff 的临时文件 table 以复制您正在尝试执行的操作。如您所见,每个 FirstDayPeriod 日期都是循环的,然后对前 12 个月的 NrOfThings 求和。然后根据 FirstDayPeriod 更新 NrOfthingsPastYear。您可以在此处轻松地增加指标等内容的范围,但下面应该为您提供一个基础:
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
只是加入和分组的问题。查询应该是相对不言自明的。只需获取 table 的每一行,然后将其与之前的 11 个月连接起来。然后对该行的日期进行分组(应该有 12 个)并添加连接值。
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;
having
子句可防止出现部分结果,但您可以根据需要省略它。
将其转换为 update
语句会因为分组而有点棘手。如果不出意外,只需将此结果集反馈到与 table 的连接中并使用它。
这里是Fiddle。它使用 SQL 服务器,因为 SQLFiddle 没有 Sybase,但它会关闭。
我想我应该在家里安装 Sybase...
我下面有这个table:
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
最后一列 (NmbrOfThingsPastYear
) 是过去 12 个月 NrOfThings
的总数。因此,2014 年 11 月的 NmbrOfThingsPastYear
由 2014 年 11 月、2014 年 10 月、2014 年 9 月等的 NrOfThings
的总和定义...直到 2013 年 12 月...
我想做的是用 table...
NmbrOfThingsPastYear
此声明提供了 2014 年 11 月的正确值:
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
所以我正在寻找一种结构,我可以在其中使用值更新 table 中每一行的 NmbrOfThingsPastYear
列(前面 NrOfThings
的总和12个月)每个月..
有人可以帮助我吗? 提前致谢!
我已经实现了你想要的,但是使用了游标。如果有人转换这个或 post 基于集合的逻辑,那么就用那个。
我创建了一个名为 #stuff 的临时文件 table 以复制您正在尝试执行的操作。如您所见,每个 FirstDayPeriod 日期都是循环的,然后对前 12 个月的 NrOfThings 求和。然后根据 FirstDayPeriod 更新 NrOfthingsPastYear。您可以在此处轻松地增加指标等内容的范围,但下面应该为您提供一个基础:
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
只是加入和分组的问题。查询应该是相对不言自明的。只需获取 table 的每一行,然后将其与之前的 11 个月连接起来。然后对该行的日期进行分组(应该有 12 个)并添加连接值。
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;
having
子句可防止出现部分结果,但您可以根据需要省略它。
将其转换为 update
语句会因为分组而有点棘手。如果不出意外,只需将此结果集反馈到与 table 的连接中并使用它。
这里是Fiddle。它使用 SQL 服务器,因为 SQLFiddle 没有 Sybase,但它会关闭。
我想我应该在家里安装 Sybase...