Как заменить все предыдущие значения на основе последнего значения SQL Server 2017 - PullRequest
2 голосов
/ 09 января 2020

Пример данных:

declare @T1 table 
            (
                ClaimID int, 
                Person varchar(20), 
                TransactionDate date,
                Status varchar(20)
            )

insert into @T1 
values (1, 'Person1', '2018-03-05','Open')
  ,(1, 'Person2', '2018-03-10','Open')
  ,(1, 'Person2', '2018-03-15','Closed')
  ,(2, 'Person3', '2018-03-15','Open')
  ,(2, 'Person3', '2018-03-23','Closed')
  ,(3, 'Person4', '2018-04-18','Closed')
  ,(4, 'Person5', '2018-04-23','Open')
  ,(4, 'Person5', '2018-04-25','Open')

select *
from @T1 t2
where TransactionDate <= '2018-12-31'
order by ClaimID, TransactionDate

Вывод будет выглядеть следующим образом:

enter image description here

Мне нужно создать столбец логических значений is_Open. Например, Person2 в последнем TransactionDate имел Status "Closed", поэтому значение для этой строки и всех предыдущих строк для Person2 должно быть 0.

То же самое для Person3 - его был закрыт на 2018-03-23, поэтому все предыдущие значения для Person3 должны быть 0.

Но Person5 имеет Status "Open" в последнюю TransactionDate, поэтому значение для этой (последнейactionDate) должно быть 1 но для предыдущего TransactionDate должно быть 0, даже если status равно Open

Для столбца is_Open:

Если последний TransactionDate для Person имеет Status Open, затем 1, все предыдущие транзакции 0. Если последняя транзакция имеет статус Закрыто, то 0 и все предыдущие транзакции 0.

Для столбца is_Closed:

Если последние TransactionDate для Person имеют Status Closed, то 1, все предыдущие транзакции 0.Если последние TransactionDate для Person имеют Status Open, то 0 и все предыдущие транзакции 0.

Результат должен выглядеть следующим образом:

enter image description here

Я пытался использовать ROW_NUMBER() и LAST_VALUE функции, но до сих пор не могу понять:

select
    *,
    row_number() over (partition by  ClaimID order by TransactionDate) as rowNum,
    iif(last_value(Status) over (partition by Person order by TransactionDate desc) = 'Closed', 1, 0) as LastValue
from 
    @T1 t2
where 
    TransactionDate <= '2018-12-31'
order by 
    ClaimID, TransactionDate

Ответы [ 4 ]

1 голос
/ 09 января 2020

Я полагаю, что это будет желаемый результат. IsOpen проверяет следующую строку для конкретного клиента и, если есть открытый или закрытый статус - закрывает текущую строку, то же самое происходит с isClosed, однако в противоположных логиках c:

select *,case 
    when ClaimStatus = 'Closed' then 0
    when lead(ClaimStatus) over(partition by ClaimantID order by transactiondate asc) = 'Closed' 
        or lead(ClaimStatus) over(partition by ClaimantID order by transactiondate asc) = 'Open' then 0
    else 1
 end as is_Open
     from @T1

Кроме того, этот способ проще и дает тот же результат. Поправь меня, если я ошибаюсь:

declare @T1 table 
            (
                ClaimID int, 
                Claimant varchar(20), 
                TransactionDate date,
                ClaimStatus varchar(20)
            )

insert into @T1 
values 
   (1, 'Claimant1', '2018-03-05','Open')
  ,(1, 'Claimant1', '2018-02-05','Open')
  ,(1, 'Claimant2', '2018-03-10','Open')
  ,(1, 'Claimant2', '2018-03-15','Closed')
  ,(2, 'Claimant3', '2018-03-15','Open')
  ,(2, 'Claimant3', '2018-03-23','Closed')
  ,(3, 'Claimant4', '2018-04-18','Closed')
  ,(4, 'Claimant5', '2018-04-23','Open')
  ,(4, 'Claimant5', '2018-04-25','Open')
  ,(5, 'Claimant6', '2018-05-18','Open')
  ,(5, 'Claimant6', '2018-05-23','Open')

select *,
iif(ROW_NUMBER() OVER(PARTITION BY Claimant ORDER BY TransactionDate desc) = 1 and ClaimStatus = 'Open',1,0) AS is_Open
from @T1 t2
where TransactionDate <= '2018-12-31'
order by ClaimID, TransactionDate
0 голосов
/ 09 января 2020
select claimid, person, transactiondate, status, 
if( lead(lastvalue) over(partition by person order by transactiondate ) = 'open', 0, 1) and if(lastvalue = 'open', 1, 0) as is_open,
if(status = 'open', 0, 1) as is_close
from 
(
select *, last_value(status) over ( partition by person order by transactiondate ROWS BETWEEN unbounded preceding and unbounded following) as lastvalue from sales.T1 ) T;

Здесь вывод.

Результат

0 голосов
/ 09 января 2020
select t2.*, (case when last_value([status]) over 
                        (partition by Person order by TransactionDate 
                         rows between current row and unbounded following
                        ) = 'Closed' 
                   then 0 else 1 
           end) as is_open,
          ( case when Status='Open' then 0 else 1 end )as is_Closed
from @T1 t2
where TransactionDate <= '2018-12-31'
order by ClaimID, TransactionDate;
0 голосов
/ 09 января 2020

LAST_VALUE() не имеет рамок по умолчанию, поэтому вам нужно использовать оконную функцию:

select t2.*, (case when last_value([status]) over 
                        (partition by Person order by TransactionDate 
                         rows between current row and unbounded following
                        ) = 'Closed' 
                   then 0 else 1 
           end) as is_open
from @T1 t2
where TransactionDate <= '2018-12-31'
order by ClaimID, TransactionDate;

РЕДАКТИРОВАТЬ:

select *, (case when lastval = 'Closed' 
                then 0
                when lastval <> 'Closed' and cnt > seq
                then 0 
                else 1 
           end) as is_open,
          (case when lastval = 'Closed' and seq = cnt  
                then 1
                when lastval = 'Closed' and seq < cnt
                then 0 
                else 0 
           end) as is_close
from (select T2.*, last_value([status]) over 
                  (partition by Person order by TransactionDate 
                   rows between current row and unbounded following
                  ) as lastval,
                  count(*) over (partition by Person) as cnt,
                  row_number() over (partition by Person order by TransactionDate) as seq
      from @T1 t2
      where TransactionDate <= '2018-12-31'
     ) t;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...