Selecionar linhas começando do valor especificado até outro valor especificado


8

Eu tenho uma tabela contendo várias colunas e quero verificar um valor de coluna, selecione as linhas após esse valor até que um valor de coluna separado apareça. Eu tentei usar BETWEEN, mas se os valores da coluna são números inteiros, ele procura apenas números entre os números inteiros.

Por exemplo, se eu tiver uma tabela como esta:

valor do tempo de identificação 
t1 12:00 15
t1 12:02 4
t1 12:03 7
t1 12:05 16
t5 12:10 PM 250
t5 12:15 15
t8 11:00 15
t8 15:00 2
t8 15:05 100
t2 19:00 15
t2 19:01 16
t15 5:00 35 

Eu gostaria de obter as linhas entre os valores de 15 e 16. Basicamente, se eu pudesse classificar por id, então time, e reunir as linhas após 15 aparecer até que haja um valor de 16 dentro do mesmo id. Se não houver valor 16, eu desejaria as próximas 100 linhas, por exemplo, e depois procuraria o próximo valor de 15.

Gostaria que a consulta retornasse isso:

valor do tempo de identificação 
t1 12:00 15
t1 12:02 4
t1 12:03 7
t1 12:05 16
t2 19:00 15
t2 19:01 16
t5 12:15 15
t8 11:00 15
t8 15:00 2
t8 15:05 100

Isso pode ser confuso. Eu tentei:

SELECT * FROM table WHERE value BETWEEN '15' AND '16' ORDER BY id, time

como ponto de partida, mas que retorna somente linhas com valores de 15 ou 16 porque são números inteiros.

Quero ordenar a mesa até idtime. Essas entradas são adicionadas automaticamente através de outro sistema, por isso estou tentando consultar a tabela para intervalos de valores específicos.

Alguma ideia?

Esclarecimento:

Se eu tivesse linhas com 15, 1, 16, 7, 15, 2, 16a mesma id, eu gostaria tanto "ilhas": 15, 1, 16, 15, 2, 16.


Como você deseja que a solução lide com um caso em que um 15 foi encontrado e depois de alguns valores que não são 16, há outro valor 15?
David Markovitz

@DuduMarkovitz Após 100 valores, se nenhum valor de 16 for encontrado, eu gostaria de começar de novo no próximo valor 15. Se houver outro valor de 15 após menos de 100 valores, ele deve começar novamente. Para meus propósitos, isso raramente deveria acontecer. É uma pergunta válida embora.
Link

Obrigado. felizmente, é assim que as soluções atuais já são tratadas.
David Markovitz

Respostas:


7

Uma sugestão que deve funcionar na versão 2008.

Testado em rextester.com :

with 
  end_points as                       -- find start and end points
    ( select id, time, value
      from table_x
      where value in (15, 16)
    ), 
  start_points as                     -- only the start points
    ( select id, time, value
      from end_points
      where value = 15
    )
select 
    t.id, t.time, t.value
from
    start_points as s
  outer apply                         -- find where each island ends
    ( select top (1) ep.* 
      from end_points as ep
      where s.id   = ep.id
        and s.time < ep.time
      order by ep.time
    ) as e
  cross apply                         -- and run through each island
    ( select p.id, p.time, p.value, 
             rn = row_number() over (order by p.time) 
      from table_x as p
      where s.id   = p.id
        and s.time <= p.time
        and         ( p.time < e.time
                   or p.time = e.time and e.value = 16
                   or          e.time is null)
    ) as t
where 
    t.rn <= 100
order by
    t.id, t.time  ;

Mais informações:


1
select id,time,value

from   (select  *
               ,min (case when value = 16 then rn end) over 
                (
                    partition by    id,grp_id
                ) as min_rn_16

        from   (select  *
                       ,row_number () over 
                        (
                            partition by    id,grp_id 
                            order by        time
                        ) as rn

                from   (select      *
                                   ,count (case when value = 15 then 1 end) over 
                                    (
                                        partition by    id 
                                        order by        time 
                                        rows            unbounded preceding
                                    ) as grp_id

                        from        mytab
                        ) t

                where   grp_id > 0
                ) t

        where   rn <= 100
        ) t

where   rn <= coalesce (min_rn_16,100)

2
Está na versão 2008. Não é COUNT(*) OVER (ORDER BY ..)permitido.
ypercubeᵀᴹ

Parece ótimo e me faz perceber que preciso ler um pouco mais para entender o que tudo isso faz. Obrigado pela contribuição.
Link
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.