Seleziona le righe a partire dal valore specificato fino a un altro valore specificato


8

Ho una tabella contenente più colonne e voglio verificare il valore di una colonna, selezionare le righe dopo quel valore di colonna fino a quando non viene visualizzato un valore di colonna separato. Ho provato a usare BETWEEN, ma se i valori di colonna sono numeri interi cerca solo numeri tra i numeri interi.

Ad esempio, se ho una tabella come questa:

valore tempo id 
t1 12:00 PM 15
T1 12:02 4
t1 12:03 PM 7
T1 12:05 16
t5 12:10 PM 250
t5 12:15 PM 15
t8 11:00 AM 15
t8 3:00 PM 2
t8 15:05 100
T2 19:00 15
T2 19:01 16
t15 5:00 AM 35 

Vorrei ottenere le righe tra i valori di 15 e 16. Fondamentalmente, se potessi ordinare per id, quindi time, e raccogliere le righe dopo che appare 15 finché non vi è un valore di 16 all'interno di quello stesso id. Se non esiste un valore 16, ad esempio vorrei le successive 100 righe e quindi cerco il valore successivo di 15.

Vorrei che la query restituisse questo:

valore tempo id 
t1 12:00 PM 15
T1 12:02 4
t1 12:03 PM 7
T1 12:05 16
T2 19:00 15
T2 19:01 16
t5 12:15 PM 15
t8 11:00 AM 15
t8 3:00 PM 2
t8 15:05 100

Potrebbe essere fonte di confusione. Ho provato:

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

come punto di partenza, ma restituisce solo righe con valori di 15 o 16 perché sono numeri interi.

Voglio ordinare la tabella per idallora time. Queste voci vengono aggiunte automaticamente tramite un altro sistema, quindi sto cercando di interrogare la tabella per intervalli di valori specifici.

Qualche idea?

Una precisazione:

Se avessi le righe con 15, 1, 16, 7, 15, 2, 16la stessa id, vorrei entrambe le "isole": 15, 1, 16, 15, 2, 16.


Come vuoi che la soluzione gestisca un caso in cui è stato trovato un 15 e dopo alcuni valori che non sono 16, c'è un altro valore 15?
David Markovitz,

@DuduMarkovitz Dopo 100 valori se non viene trovato alcun valore di 16, vorrei ricominciare dal prossimo 15. Se c'è un altro valore di 15 dopo meno di 100 valori, dovrebbe ricominciare da capo. Per i miei scopi, ciò dovrebbe accadere raramente se non del tutto. È una domanda valida però.
Link

Grazie. fortunatamente questo è il modo in cui è già gestito dalle soluzioni attuali.
David Markו Markו Markovitz,

Risposte:


7

Un suggerimento che dovrebbe funzionare nella versione 2008.

Testato su 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  ;

Ulteriori informazioni:


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
È nella versione 2008. Non COUNT(*) OVER (ORDER BY ..)permesso
ypercubeᵀᴹ

Sembra fantastico e mi fa capire che devo leggere un po 'di più per capire cosa fa tutto questo. Grazie per l'input.
Link
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.