TSQL - ссылка на измененное значение из предыдущей строки - PullRequest
0 голосов
/ 16 ноября 2018

Я пытаюсь выполнить вычисление строки, в результате чего большее значение будет перенесено в последующие строки, пока не будет сопоставлено большее значение.Это делается путем сравнения текущего значения с предыдущей строкой с использованием функции lag ().

Код

DECLARE @TAB TABLE (id varchar(1),d1 INT , d2 INT)

INSERT INTO @TAB (id,d1,d2) 

VALUES ('A',0,5)
      ,('A',1,2)
      ,('A',2,4) 
      ,('A',3,6)
      ,('B',0,4)
      ,('B',2,3)
      ,('B',3,2)
      ,('B',4,5)

SELECT id
      ,d1
      ,d2 = CASE WHEN id <> (LAG(id,1,0) OVER (ORDER BY id,d1)) THEN d2
                 WHEN d2 < (LAG(d2,1,0) OVER (ORDER BY id,d1)) THEN (LAG(d2,1,0) OVER (ORDER BY id,d1)) 
                 ELSE d2 END

Вывод (для ясности добавлена ​​строка od2)

     +----+----+----+    +----+
     | id | d1 | d2 |    | od2|
     +----+----+----+    +----+
     | A  |  0 |  5 |    |  5 |
     | A  |  1 |  5 |    |  2 |
     | A  |  2 |  4 |    |  4 |
     | A  |  3 |  6 |    |  6 |
     | B  |  0 |  4 |    |  4 |
     | B  |  2 |  4 |    |  3 |
     | B  |  3 |  3 |    |  2 |
     | B  |  4 |  5 |    |  5 |
     +----+----+----+    +----+

Как видно из вывода, функция задержки ссылается на исходное значение предыдущей строки, а не на новое значение.Есть ли способ достичь этого?

Желаемый результат

     +----+----+----+    +----+
     | id | d1 | d2 |    | od2|
     +----+----+----+    +----+
     | A  |  0 |  5 |    |  5 |
     | A  |  1 |  5 |    |  2 |
     | A  |  2 |  5 |    |  4 |
     | A  |  3 |  6 |    |  6 |
     | B  |  0 |  4 |    |  4 |
     | B  |  2 |  4 |    |  3 |
     | B  |  3 |  4 |    |  2 |
     | B  |  4 |  5 |    |  5 |
     +----+----+----+    +----+

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Спасибо за предоставление сценариев DDL и DML.

Один из способов сделать это - использовать рекурсивный cte следующим образом.1. Сначала оцените все записи в соответствии с id, d1 и d2.-> Блок cte 2. Используйте рекурсивный cte и получите первые элементы, используя rnk = 1. 3. Поле «сравнении_значения» проверит значения предыдущего РНК, чтобы определить, является ли значение> существующим, и если да, то оно поменяется местами.

DECLARE @TAB TABLE (id varchar(1),d1 INT , d2 INT)

INSERT INTO @TAB (id,d1,d2) 

VALUES ('A',0,5)
      ,('A',1,2)
      ,('A',2,4) 
      ,('A',3,6)
      ,('B',0,4)
      ,('B',2,3)
      ,('B',3,2)
      ,('B',4,5)

;with cte
  as (select row_number() over(partition by id order by d1,d2) as rnk
            ,id,d1,d2     
        from @TAB    
      )
  ,data(rnk,id,d1,d2,compared_val)
    as (select rnk,id,d1,d2,d2 as compared_val
          from cte
         where rnk=1
         union all
        select a.rnk,a.id,a.d1,a.d2,case when b.compared_val > a.d2 then 
                                              b.compared_val 
                                         else a.d2
                                      end
          from cte a
          join data b
            on a.id=b.id
           and a.rnk=b.rnk+1
        )
select * from data order by id,d1,d2
0 голосов
/ 16 ноября 2018

Попробуйте это:

SELECT id
      ,d1
      ,d2  
     ,MAX(d2) OVER (PARTITION BY ID ORDER BY d1)
FROM @TAB 

enter image description here

Идея состоит в том, чтобы использовать MAX для получения максимального значения от начала до текущей строки для каждого раздела.

...