2015-02-25 3 views
2

Есть ли способ использовать ведущую функцию, чтобы я мог получить следующую строку, где что-то изменилось, в противоположность тому, где это то же самое?TSQL - LEAD для следующей разной строки

В этом примере RowType может быть «in» или «out», для каждого «in» мне нужно знать следующий RowNumber, где он стал «out». Я играю с ведущей функцией, так как это очень быстро, однако я не смог заставить ее работать. Мне просто нужно сделать следующее: это раздел с помощью RowType, который не является в текущей строке.

select 
RowNumber 
,RowType --In this case I am only interested in RowType = 'In' 
, Lead(RowNumber) 
    OVER (partition by "RowType = out" --This is the bit I am stuck on-- 
      order by RowNumber ASC) as NextOutFlow 
from table 
order by RowNumber asc 

Заранее спасибо за любую помощь

ответ

1

Вместо того чтобы использовать lead() Я хотел бы использовать outer apply, который возвращает следующую строку с типом out для всех строк с типом in:

select RowNumber, RowType, nextOut 
from your_table t 
outer apply (
    select min(RowNumber) as nextOut 
    from your_table 
    where RowNumber > t.RowNumber and RowType='Out' 
) oa 
where RowType = 'In' 
order by RowNumber asc 

Учитывая образца данные, такие как:

RowNumber RowType 
1   in 
2   out 
3   in 
4   in 
5   out 
6   in 

Это возвращение:

RowNumber RowType nextOut 
1   in  2 
3   in  5 
4   in  5 
6   in  NULL 
+0

Использование внешнего применения Процесс занимает примерно 2 часа, тогда как если бы ведущая функция могла работать, это может потребоваться только несколько секунд. (Использование ввода только для получения следующей строки в настоящее время занимает 4 в моем наборе данных). – SomeGuy30145

+0

@ SomeGuy30145 Я не ожидал, что внешние приложения будут применяться так долго - могу ли я спросить, насколько большой набор данных, с которым вы работаете? Я не мог придумать способ использовать 'lead()', чтобы сделать это, хотя, возможно, это возможно. – jpw

+0

Примерно 2 миллиона строк – SomeGuy30145

0

Я думаю, что это будет работать
Если вы будете использовать битовое поле для во вне, вы получите более высокую производительность

;with cte1 as 
(
    SELECT [inden], [OnOff] 
     , lag([OnOff]) over (order by [inden]) as [lagOnOff] 
    FROM [OnOff] 
), cte2 as 
(
    select [inden], [OnOff], [lagOnOff] 
     , lead([inden]) over (order by [inden]) as [Leadinden] 
    from cte1 
    where [OnOff] <> [lagOnOff] 
     or [lagOnOff] is null 
) 
select [inden], [OnOff], [lagOnOff], [Leadinden] 
    from cte2 
    where [OnOff] = 'true' 

вероятно медленнее, но если у вас есть правильные индексы может работать

select t1.rowNum as 'rowNumIn', min(t2.rownum) as 'nextRowNumOut' 
    from tabel t1 
    join table t2 
    on t1.rowType = 'In' 
    and t2.rowType = 'Out' 
    and t2.rowNum > t1.rowNum 
    and t2.rowNum < t1.rowNum + 1000 -- if you can constrain it 
group by t1.rowNum 
+0

первый работает очень быстро, как быстрее, чем просто вызов таблицы, которая потрясающая. Однако он получает только первый экземпляр «In», а затем следующий «out», если есть последовательный «in» - они должны оба получать одинаковые «выходные», - показывает результат другого предложения. Я изменил поле inout так, как вы предлагали. – SomeGuy30145

+0

Ouch. Если вам нужно перепрыгнуть несколько строк, то почему вы считаете, что свинца/запаздывания будет правильным? – Paparazzi

+0

Я не знал, будет ли это правильный подход, но если он сработает, это может быть очень быстро. – SomeGuy30145

Смежные вопросы