2014-11-19 5 views
0

У меня есть набор результатов, как это:Изменение текущей строки на основе предыдущей строки в SQL-сервере

YearMonth Sales 
201411  100 
201412  100 
201501  100 
201502  100 
201503  100 
201504  100 
201505  100 
201506  100 
201507  100 
201508  100 

нужно добавить еще одну строку с 4% больше продаж, чем в предыдущем месяце. Например, мой результат должен быть

YearMonth Sales New Sales 
201411  100 100.00 
201412  100 104.00 
201501  100 108.16 
201502  100 112.49 
201503  100 116.99 
201504  100 121.67 
201505  100 126.53 
201506  100 131.59 
201507  100 136.86 
201508  100 142.33 

Пожалуйста, помогите мне получить наилучший путь для этого.

+0

Что тип данных столбца годМесяц? Char или целое число? Всегда ли YearMonth постоянно? Если нет, как рассчитать следующие продажи после пробела? –

+0

Месяц 07/2015 имеет продажи = 100, таким образом, следующий месяц 08/2015 должен иметь продажи = 104, а не 142.33. –

+0

Дополнительные 4% на 100 будут равны 104 для всех значений. Вы не упомянули, чтобы рассчитать стоимость новой продажи. –

ответ

0

Получил отличный ответ для ваших требований. Понадобилось много времени, чтобы разобраться. Просто измените имя таблицы #Temp на имя таблицы и проверьте имена столбцов.

DECLARE @nCurrentSale FLOAT 
DECLARE @nYeatDate INT 
DECLARE @nSale FLOAT 

CREATE TABLE #TempNEW(YearMonth VARCHAR(10), Sales FLOAT, NewSale FLOAT) 
SELECT TOP 1 @nCurrentSale = Sales FROM #Temp 
    ORDER BY (CAST('01/' + SUBSTRING (CAST(YearMonth AS VARCHAR), 5 , 2) + '/' + SUBSTRING (CAST(YearMonth AS 
     VARCHAR), 0 , 5) AS DATETIME)) ASC 

DECLARE Cursor1 CURSOR FOR 
     SELECT YearMonth, Sales FROM #Temp 
     ORDER BY (CAST('01/' + SUBSTRING (CAST(YearMonth AS VARCHAR), 5 , 2) + '/' + SUBSTRING (CAST(YearMonth AS 
      VARCHAR), 0 , 5) AS DATETIME)) ASC 

    OPEN Cursor1 

    FETCH NEXT FROM Cursor1 INTO @nYeatDate, @nSale 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     INSERT INTO #TempNEW(YearMonth, Sales, NewSale) VALUES(@nYeatDate, @nSale, CAST(@nCurrentSale AS DECIMAL(12,2))) 

     SET @nCurrentSale = @nCurrentSale + ((@nCurrentSale/100) * 4) 

     FETCH NEXT FROM Cursor1 INTO @nYeatDate, @nSale 
    END 

    CLOSE Cursor1 
    DEALLOCATE Cursor1 

SELECT * FROM #TempNEW 

Сообщите мне о вашем статусе.

+0

Большое спасибо Veera .. Фактически, мой исходный набор данных не является таблицей, а извлекается из запроса вместе со многими другими полями. Сейчас я работаю над этим. Еще раз спасибо!! – user2910717

+0

Есть ли другой способ, который мы можем сделать в Server 2012, поскольку мой набор данных содержит 10 миллионов строк, и может быть медленным использование курсора. – user2910717

+0

Я ПЫТАЮТСЯ К РИСУНКУ – Veera

0

Да, это возможно. Но сначала вам нужно изменить таблицу и добавить дополнительный столбец NewSales, а затем попробовать по этой ссылке https://dba.stackexchange.com/questions/34243/update-row-based-on-match-to-previous-row Я думаю, вы можете сделать это по этой ссылке Также сервер sql поддерживает некоторые «Вычислительные столбцы в SQL Server с сохраненными значениями» , используя это вы можете указать формулу, что хотите, то новое значение столбца будет автоматически создано в соответствии с вашей формулой

0

Вот две мысли ... Не очень понятно, если я понял случай использования ... Кроме того, это решение будет работать только для SQL 2012 и выше

Так дали таблицу

CREATE TABLE [dbo].[LagExample](
    [YearMonth] [nvarchar](100) NOT NULL, 
    [Sales] [money] NOT NULL 
) 

Первый один довольно прост и просто предполагает, что вы желая обосновать величину вашего процентного увеличения на сколько дней были до него ...

;WITH cte 
as 
(
    SELECT YearMonth, 
     ROW_NUMBER() OVER (ORDER BY YearMonth) - 1 AS SalesEntry, 
     cast(LAG(Sales, 1,Sales) OVER (ORDER BY YearMonth) as float) as Sales 
    FROM LagExample 
) 
SELECT YearMonth, 
     Sales, 
     cast(Sales * POWER(cast(1.04 as float), SalesEntry) AS decimal(10,2)) as NewSales 
FROM cte 

второго один использует рекурсивный КТР для вычислить значение по мере продвижения вдоль месяцев .. Вот хорошая ссылка про рекурсивных КТР http://www.codeproject.com/Articles/683011/How-to-use-recursive-CTE-calls-in-T-SQL

;with data 
as 
(
    SELECT Lead(le.YearMonth, 1, null) OVER (ORDER BY le.YearMonth) as NextYearMonth, 
      cast(le.Sales as Decimal(10,4)) as Sales, 
      le.YearMonth 
    FROM LagExample le 
) 
,cte 
as 
(
    SELECT * 
    FROM data 
    Where YearMonth = '201411' 
    UNION ALL 
    SELECT 
     data.NextYearMonth, 
     cast(cte.Sales * 1.04 as Decimal(10,4)) as Sales, 
     data.YearMonth 
    From cte join 
     data on data.YearMonth = cte.NextYearMonth 
) 
SELECT YearMonth, cast(Sales as Decimal(10,2)) 
FROM cte 
order by YearMonth 
Смежные вопросы