САМ СОЕДИНЯЙТЕСЬ, чтобы обновить строки таблицы - PullRequest
2 голосов
/ 02 марта 2012

У меня есть таблица с этими столбцами

- ProjectId
 - Generation
 - Expected 
 - CarryOver

Я пытаюсь обновить свою уже заполненную таблицу следующим образом:

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

, где предыдущая строка и текущая строка имеют одинаковые значения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

Original Ouput.Перед запуском запроса на обновление:

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 голосов
/ 03 марта 2012

Извините за путаницу. Вот мое предложение.

Данные испытаний

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
0 голосов
/ 06 марта 2012

Вот как я это сделал:

Для обновления первой записи, соответствующей каждому 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
0 голосов
/ 03 марта 2012

Следующий запрос даст ожидаемые результаты

(тестовый код 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

Youнужно сделать это в цикле.Используемый вами запрос получает исходное значение столбца переноса, а не обновленное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...