Выберите строки, начиная с указанного значения до другого указанного значения


8

У меня есть таблица, содержащая несколько столбцов, и я хочу проверить значение столбца, выбирать строки после этого значения столбца, пока не появится отдельное значение столбца. Я попытался с помощью BETWEEN, но если значения столбца являются целыми числами, он ищет только числа между целыми числами.

Например, если у меня есть такая таблица:

значение времени идентификатора 
t1 12:00 PM 15
t1 12:02 PM 4
t1 12:03 PM 7
t1 12:05 PM 16
t5 12:10 250
t5 12:15 15
t8 11:00 15
t8 3:00 PM 2
t8 15:05 100
t2 7:00 вечера 15
t2 7:01 PM 16
t15 5:00 AM 35 

Я хотел бы получить строки между значениями 15 и 16. В принципе, если бы я мог отсортировать по id, то timeи собирать строки после появления 15, пока не будет значение 16 в том же самом id. Если значения 16 нет, я хотел бы, например, следующие 100 строк, а затем искать следующее значение 15.

Я хотел бы запрос вернуть это:

значение времени идентификатора 
t1 12:00 PM 15
t1 12:02 PM 4
t1 12:03 PM 7
t1 12:05 PM 16
t2 7:00 вечера 15
t2 7:01 PM 16
t5 12:15 15
t8 11:00 15
t8 3:00 PM 2
t8 15:05 100

Это может сбивать с толку. Я пробовал:

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

в качестве отправной точки, но это только возвращает строки со значениями 15 или 16, потому что они являются целыми числами.

Я хочу отсортировать таблицу к тому idвремени time. Эти записи добавляются автоматически через другую систему, поэтому я пытаюсь запросить таблицу для определенных диапазонов значений.

Любые идеи?

Разъяснение:

Если бы я имел строки с 15, 1, 16, 7, 15, 2, 16для того же id, я хотел бы как «острова»: 15, 1, 16, 15, 2, 16.


Как вы хотите, чтобы решение обрабатывало случай, когда было найдено 15, и после некоторых значений, которые не являются 16, есть еще одно значение 15?
Дэвид Markודו Марковиц

@DuduMarkovitz После 100 значений, если значение 16 не найдено, я бы хотел начать с следующих 15 значений. Если есть другое значение 15 после менее чем 100 значений, оно должно начаться снова. В моих целях это случается редко, если вообще происходит. Это правильный вопрос, хотя.
ссылка

Спасибо. К счастью, это так, как это уже обрабатывается текущими решениями.
Дэвид דודו Марковиц

Ответы:


7

Предложение, которое должно работать в версии 2008 года.

Протестировано на 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  ;

Больше информации:


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
Это в версии 2008 года. Не COUNT(*) OVER (ORDER BY ..)допускается
ypercubeᵀᴹ

Выглядит отлично и заставляет меня понять, что мне нужно прочитать немного больше, чтобы понять, что все это делает. Спасибо за вклад.
ссылка
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.