Seleccione filas comenzando desde el valor especificado hasta otro valor especificado


8

Tengo una tabla que contiene varias columnas y quiero verificar el valor de una columna, seleccionar las filas después de ese valor de columna hasta que aparezca un valor de columna separado. He intentado usar BETWEEN, pero si los valores de la columna son enteros, solo busca números entre los enteros.

Por ejemplo, si tengo una tabla como esta:

valor de tiempo de identificación 
t1 12:00 PM 15
t1 12:02 PM 4
t1 12:03 PM 7
t1 12:05 PM 16
t5 12:10 PM 250
t5 12:15 PM 15
t8 11:00 AM 15
t8 3:00 PM 2
t8 3:05 PM 100
t2 7:00 PM 15
t2 7:01 PM 16
t15 5:00 AM 35 

Me gustaría obtener las filas entre valores de 15 y 16. Básicamente, si pudiera ordenar por id, entonces time, y reunir las filas después de que aparezca 15 hasta que haya un valor de 16 dentro de ese mismo id. Si no hay un valor 16, quisiera las siguientes 100 filas, por ejemplo, y luego buscar el siguiente valor de 15.

Me gustaría que la consulta devuelva esto:

valor de tiempo de identificación 
t1 12:00 PM 15
t1 12:02 PM 4
t1 12:03 PM 7
t1 12:05 PM 16
t2 7:00 PM 15
t2 7:01 PM 16
t5 12:15 PM 15
t8 11:00 AM 15
t8 3:00 PM 2
t8 3:05 PM 100

Eso puede ser confuso. He intentado:

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

como punto de partida, pero eso solo devuelve filas con valores de 15 o 16 porque son enteros.

Quiero ordenar la mesa para identonces time. Estas entradas se agregan automáticamente a través de otro sistema, así que estoy tratando de consultar en la tabla los rangos de valores específicos.

¿Algunas ideas?

Aclaración:

Si tuviera filas con 15, 1, 16, 7, 15, 2, 16el mismo id, me gustaría que los dos "islas": 15, 1, 16, 15, 2, 16.


¿Cómo desea que la solución maneje un caso en el que se encontró un 15 y después de algunos valores que no son 16, hay otro valor de 15?
David דודו Markovitz

@DuduMarkovitz Después de 100 valores si no se encuentra ningún valor de 16, me gustaría comenzar de nuevo en el siguiente valor de 15. Si hay otro valor de 15 después de menos de 100 valores, debería comenzar de nuevo. Para mis propósitos, esto rara vez debería suceder si es que lo hace. Sin embargo, es una pregunta válida.
Enlace

Gracias. Afortunadamente, esta es la forma en que las soluciones actuales ya la manejan.
David דודו Markovitz

Respuestas:


7

Una sugerencia que debería funcionar en la versión 2008.

Probado en 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  ;

Más información:


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á en la versión 2008. No COUNT(*) OVER (ORDER BY ..)permitido
ypercubeᵀᴹ

Se ve genial y me hace darme cuenta de que necesito leer un poco más para entender lo que hace todo esto. Gracias por el aporte.
Enlace
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.