необходимо изменить запрос без использования перекрестного / внешнего применения - PullRequest
2 голосов
/ 24 мая 2019
create table PrinterData(
    Dt DateTime not null,
    Status nvarchar(50) not null    
)

insert into PrinterData
values
('05.24.2019 00:00:00', 'READY'),
('05.24.2019 00:01:00', 'READY'),
('05.24.2019 00:02:00', 'NO PAPER'),
('05.24.2019 00:03:00', 'UNKNOWN'),
('05.24.2019 00:04:00', 'UNKNOWN'),
('05.24.2019 00:05:00', 'READY'),
('05.24.2019 00:06:00', 'READY'),
('05.24.2019 00:07:00', 'READY'),
('05.24.2019 00:08:00', 'NO PAPER'),
('05.24.2019 00:09:00', 'UNKNOWN'),
('05.24.2019 00:10:00', 'HAS PAPER'),
('05.24.2019 00:11:00', 'NO PAPER')

Мне нужно знать интервал времени между ГОТОВЫМ статусом и следующим ГОТОВЫМ или ИМЕЕТ БУМАГУ , кроме НЕИЗВЕСТНО статуса, НЕИЗВЕСТНО мне нужно пропустить.Результат должен выглядеть следующим образом:

enter image description here

Это мой запрос, но я не люблю использовать cross / external apply.С точки зрения производительности и скорости мне нужно ваше предложение, как изменить этот запрос.

select a.Dt, a.Status, b.Dt as Dt_Next_Status, b.Status as Next_Status, DATEDIFF(SECOND, a.Dt, b.Dt) as Diff from PrinterData a
outer apply 
(
    select top 1  Dt, Status from PrinterData where Dt > a.Dt and Status not in ('UNKNOWN', 'NO PAPER') 
) b
where a.Status = 'NO PAPER' 

Ответы [ 2 ]

2 голосов
/ 24 мая 2019

Использование lead() функция

DEMO

select *,datediff(SECOND,dt,nexttime) as diff from 
(
select *,lead(dt) over(order by dt) as nexttime,lead(status) over(order by dt) as nextstatus
from PrinterData
where Status<>'UNKNOWN'
)A where status='NO PAPER'

ВЫВОД:

Dt                  Status      nexttime            nextstatus  diff
24/05/2019 00:02:00 NO PAPER    24/05/2019 00:05:00 READY       180
24/05/2019 00:08:00 NO PAPER    24/05/2019 00:10:00 HAS PAPER   120
24/05/2019 00:11:00 NO PAPER        
1 голос
/ 24 мая 2019

вы можете сделать это, используя левое соединение и row_number ()

with cte as
(
select a.Dt, a.Status, b.Dt as Dt_Next_Status, b.Status as Next_Status,
DATEDIFF(SECOND, a.Dt, b.Dt) as Diff,
row_number()over(partition by a.DT order by b.Dt) rn
from PrinterData a
left join
(
    select  Dt, Status from PrinterData where Status not in ('UNKNOWN', 'NO PAPER') 
) b on  b.Dt > a.Dt
where a.Status = 'NO PAPER' 
) 
select * from cte where rn=1

демо в скрипке

...