自我加入更新表的行

时间:2012-03-02 09:17:21

标签: sql sql-server-2008

我有一个包含这些列的表

- ProjectId
 - Generation
 - Expected 
 - CarryOver

我正试图以这种方式更新我已经填充的表:

  Generation = Integral Part of ((Generation + CarryOver of Previous Row)/10 )
  CarryOver =  decimal part of  ((Generation + CarryOver of Previous Row)/10 )

其中Previous Row和Current Row都具有相同的projectId

以下是用于实现此目的的查询:

UPDATE TTable 

SET 

TTable.Expected=(TTable.Generation+ ISNULL(STable.CarryOver,0)),
TTable.CarryOver =(TTable.Generation+ISNULL(STable.CarryOver,0))-CONVERT(INT,(TTable.Generation+ISNULL(STable.CarryOver,0)))

FROM
(
    SELECT ROW_NUMBER()OVER(order by ProjectId,MonthYear) as RowNumber,ProjectId, 
    [MonthYear],[Month],[Generation],[Expected],[CarryOver]
    FROM #SRECEsimated 
)TTable,

(
    SELECT ROW_NUMBER()OVER(order by ProjectId,MonthYear) as RowNumber,ProjectId,
        [MonthYear],[Month],[Generation],[Expected],[CarryOver] 
    FROM #SRECEsimated 
) STable


Where   
TTable.RowNumber  = STable.RowNumber+1 AND
TTable.ProjectId = STable.ProjectId 

....但是发生了一些奇怪的事情,更新只发生在前两行。对于其他行, ISNULL(STable.CarryOver,0)返回0.为什么? 请帮我。或者提出一些其他方法来实现这个目标

编辑:运行查询

ProjectId   MonthYear   Month   Year    Generation  Expected    CarryOver
10  2011-10-01 00:00:00.000 10  2011    56.748             56            0.748
10  2011-11-01 00:00:00.000 11  2011    12.004             12            0.752
10  2011-12-01 00:00:00.000 12  2011    10.632             10            0.632
10  2012-01-01 00:00:00.000 01  2012    11.928             11            0.928
10  2012-02-01 00:00:00.000 02  2012    7.580               7            0.580
100 2011-12-01 00:00:00.000 12  2011    5.897               5            0.897
100 2012-01-01 00:00:00.000 01  2012    0.881               1            0.778

如上所示生成数据。请注意3row

之后逻辑如何不起作用

原始输出。在运行更新查询之前:

ProjectId   MonthYear   Month   Year    Generation  Expected    CarryOver
10  2011-10-01 00:00:00.000 10  2011    56.748            56             0.748
10  2011-11-01 00:00:00.000 11  2011    12.004            NULL           NULL
10  2011-12-01 00:00:00.000 12  2011    10.632            NULL           NULL
10  2012-01-01 00:00:00.000 01  2012    11.928            NULL           NULL
10  2012-02-01 00:00:00.000 02  2012    7.580             NULL           NULL
100 2011-12-01 00:00:00.000 12  2011    5.897             5           0.897
100 2012-01-01 00:00:00.000 01  2012    0.881             NULL           NULL

3 个答案:

答案 0 :(得分:0)

以下查询将为您提供预期结果

(对于那些想要玩的人来说,测试代码https://gist.github.com/1969171

PID Date       M  Y    Generation  Expected CarryOver   
10  2011-10-01 10 2011 56.748      56       0.748
10  2011-11-01 11 2011 12.004      12       0.752
10  2011-12-01 12 2011 10.632      11       0.384
10  2012-01-01 01 2012 11.928      12       0.312
10  2012-02-01 02 2012 7.58        7        0.892
100 2011-12-01 12 2011 5.897       5        0.897
100 2012-01-01 01 2012 0.881       1        0.778

DECLARE rowItems CURSOR FOR 
SELECT ProjectId, [Month], [Year], Generation FROM TTable
ORDER BY ProjectId,[Year] ,CAST([Month] as int)

DECLARE @p int, @m VARCHAR(5), @y int, @g FLOAT, @priorP int, 
        @carryOver FLOAT, @expected FLOAT

OPEN rowItems

FETCH NEXT FROM rowItems INTO @p, @m, @y, @g

SET @priorP = -1
SET @carryOver = 0.0

WHILE @@FETCH_STATUS = 0
BEGIN

   IF NOT @p = @priorP SET @carryOver = 0.0

   SET @expected = @g+@carryOver
   SET @carryOver = ROUND(@expected-FLOOR(@expected),3,0)   

   UPDATE TTable
     SET EXPECTED = FLOOR(@expected), CarryOver = @carryOver
   WHERE  ProjectId = @p and [Month] = @m and  [Year] = @y

   SET @priorP = @p

   FETCH NEXT FROM rowItems INTO @p, @m, @y, @g

END

CLOSE rowItems
DEALLOCATE rowItems

SELECT * FROM TTable

您需要循环执行此操作。您使用的查询是获取结转列的原始值而不是更新的值。

答案 1 :(得分:0)

对此表示抱歉。这是我的建议。

测试数据

CREATE TABLE TTable
        (
            ProjectId INT,
            MonthYear DATETIME, 
            Month VARCHAR(5), 
            Year INT,
            Generation FLOAT,
            Expected FLOAT,
            CarryOver FLOAT
        )
INSERT INTO TTable
VALUES
    (10,'2011-10-01 00:00:00.000','10',2011,56.748,56,0.748),
    (10,'2011-11-01 00:00:00.000','11',2011,12.004,NULL,NULL),
    (10,'2011-12-01 00:00:00.000','12',2011,10.632,NULL,NULL),
    (10,'2012-01-01 00:00:00.000','01',2012,11.928,NULL,NULL),
    (10,'2012-02-01 00:00:00.000','02',2012,7.580,NULL,NULL),
    (100,'2011-12-01 00:00:00.000','12',2011,5.897,5,0.897),
    (100,'2012-01-01 00:00:00.000','01',2012,0.881,NULL,NULL)

<强>查询

;WITH CTE
AS
(
    SELECT 
        ROW_NUMBER() OVER(ORDER BY tbl.ProjectId,tbl.Month) AS RowNbr,
        tbl.ProjectId,
        tbl.MonthYear,
        tbl.Month,
        tbl.Year,
        tbl.Generation,
        (
            FLOOR(tbl.Generation)
        ) AS Expected,
        (
            ROUND(tbl.Generation-FLOOR(tbl.Generation),3,0)
        )AS CarryOver
    FROM 
        TTable AS tbl
)
SELECT
    CTE.ProjectId,
    CTE.MonthYear,
    CTE.Month,
    CTE.Year,
    CTE.Generation,
    CTE.Expected,
    (
        CTE.CarryOver+ISNULL(Previus.CarryOver,0)
    ) AS CarryOver
FROM
    CTE
    LEFT JOIN CTE AS Previus
        ON CTE.RowNbr=Previus.RowNbr+1

<强>结果

ProjectId   MonthYear           Month   Year    Generation  Expected    CarryOver
10  2011-10-01 00:00:00.000     10      2011    56,748      56          0,748
10  2011-11-01 00:00:00.000     11      2011    12,004      12          0,752
10  2011-12-01 00:00:00.000     12      2011    10,632      10          0,636
10  2012-01-01 00:00:00.000     01      2012    11,928      11          1,56
10  2012-02-01 00:00:00.000     02      2012    7,58        7           1,508
100 2011-12-01 00:00:00.000     12      2011    5,897       5           1,477
100 2012-01-01 00:00:00.000     01      2012    0,881       0           1,778

更新查询

;WITH CTE
AS
(
    SELECT 
        ROW_NUMBER() OVER(ORDER BY tbl.ProjectId,tbl.Month) AS RowNbr,
        tbl.ProjectId,
        tbl.MonthYear,
        tbl.Month,
        tbl.Year,
        tbl.Generation,
        (
            FLOOR(tbl.Generation)
        ) AS Expected,
        (
            ROUND(tbl.Generation-FLOOR(tbl.Generation),3,0)
        )AS CarryOver
    FROM 
        TTable AS tbl
)
UPDATE TTable
SET TTable.CarryOver=CTE.CarryOver+ISNULL(Previus.CarryOver,0),
    TTable.Expected=CTE.Expected
FROM
    (
        SELECT
            ROW_NUMBER() OVER(ORDER BY TTable.ProjectId,
                                       TTable.Month) AS RowNbr,
            TTable.CarryOver,
            TTable.Expected
        FROM
            TTable
    ) AS TTable
    JOIN CTE
        ON TTable.RowNbr=CTE.RowNbr
    LEFT JOIN CTE AS Previus
        ON CTE.RowNbr=Previus.RowNbr+1

现在选择更新的表格时。然后你会得到这个结果:

ProjectId   MonthYear           Month   Year    Generation  Expected    CarryOver
10  2011-10-01 00:00:00.000     10      2011    56,748      56          0,748
10  2011-11-01 00:00:00.000     11      2011    12,004      12          0,752
10  2011-12-01 00:00:00.000     12      2011    10,632      10          0,636
10  2012-01-01 00:00:00.000     01      2012    11,928      11          1,56
10  2012-02-01 00:00:00.000     02      2012    7,58        7           1,508
100 2011-12-01 00:00:00.000     12      2011    5,897       5           1,477
100 2012-01-01 00:00:00.000     01      2012    0,881       0           1,778

答案 2 :(得分:0)

我就这样做了:

更新与每个ProjectId对应的第一条记录:

Update TTable

SET 

TTable.Expected=(TTable.Generation/10),
TTable.CarryOver =(TTable.Generation/10)-CONVERT(INT,TTable.Generation/10)


FROM
(
        SELECT ROW_NUMBER()OVER(order by ProjectId,MonthYear) as RowNumber,ProjectId, 
        [MonthYear],[Month],[Generation],[Expected],[CarryOver]
        FROM #SRECEsimated 
) TTable where TTable.RowNumber in

(
    Select Min(TTable.RowNumber)as RowNumber From
    (  
        SELECT ROW_NUMBER()OVER(order by ProjectId,MonthYear) as RowNumber,ProjectId, 
        [MonthYear],[Month],[Generation],[Expected],[CarryOver]
        FROM #SRECEsimated 
    ) as TTable GROUP by ProjectId
) 

更新其余记录:

DECLARE @RowNumber INT = -99
DECLARE @CarryOver decimal(4,3) =0
DECLARE @Expected INT =0
DECLARE @ProjectId int =0
WHILE @RowNumber IS NOT NULL
BEGIN

        SET @RowNumber= (SELECT MIN(RowNumber) FROM (
                                SELECT ROW_NUMBER()OVER(order by ProjectId,MonthYear) as RowNumber,ProjectId, 
                                [MonthYear],[Month],[Generation],[Expected],[CarryOver]
                                FROM #SRECEsimated 
                              ) as TTable 
                        WHERE TTable.RowNumber> @RowNumber)

        IF @RowNumber IS NULL
        BREAK

        SELECT @CarryOver= TTable.CarryOver,@ProjectId=TTable.ProjectId FROM 
                            (
                                SELECT ROW_NUMBER()OVER(order by ProjectId,MonthYear) as RowNumber,ProjectId, 
                                [MonthYear],[Month],[Generation],[Expected],[CarryOver]
                                FROM #SRECEsimated         
                            ) as TTable where TTable.RowNumber = @RowNumber

        UPDATE TTable
        SET TTable.Expected =(TTable.Generation+@CarryOver)/10,
        CarryOver = (TTable.Generation+@CarryOver)/10 - CONVERT(INT,(TTable.Generation+@CarryOver)/10)

        FROM                
        (
            SELECT ROW_NUMBER()OVER(order by ProjectId,MonthYear) as RowNumber,ProjectId, 
            [MonthYear],[Month],[Generation],[Expected],[CarryOver]
            FROM #SRECEsimated         
        ) as TTable where TTable.RowNumber = @RowNumber+1 AND TTable.ProjectId=@ProjectId               

END