Sélectionner des lignes à partir de la valeur spécifiée jusqu'à une autre valeur spécifiée

8

J'ai un tableau contenant plusieurs colonnes et je souhaite vérifier une valeur de colonne, sélectionnez les lignes après cette valeur de colonne jusqu'à ce qu'une valeur de colonne distincte s'affiche. J'ai essayé d'utiliser BETWEEN, mais si les valeurs de colonne sont des entiers, il ne recherche que des nombres entre les entiers.

Par exemple, si j'ai une table comme celle-ci:

valeur de temps id 
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 15 h 00 2
t8 15h05 100
t2 7:00 PM 15
t2 7:01 PM 16
t15 5:00 AM 35 

Je voudrais obtenir les lignes entre les valeurs de 15 et 16. Fondamentalement, si je pouvais trier par id, alors time, et rassembler les lignes après que 15 apparaisse jusqu'à ce qu'il y ait une valeur de 16 dans ce même id. S'il n'y a pas de valeur 16, je voudrais par exemple les 100 lignes suivantes, puis rechercher la valeur suivante de 15.

Je voudrais que la requête renvoie ceci:

valeur de temps id 
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 15 h 00 2
t8 15h05 100

Cela peut prêter à confusion. J'ai essayé:

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

comme point de départ, mais qui ne renvoie que des lignes avec des valeurs de 15 ou 16 car ce sont des entiers.

Je veux trier le tableau d'ici idtime. Ces entrées sont ajoutées automatiquement via un autre système, donc j'essaie d'interroger la table pour des plages de valeurs spécifiques.

Des idées?

Clarification:

Si j'avais des lignes avec 15, 1, 16, 7, 15, 2, 16le même id, je veux les deux « îles »: 15, 1, 16, 15, 2, 16.

Lien
la source
Comment voulez-vous que la solution gère un cas où un 15 a été trouvé et après certaines valeurs qui ne sont pas 16, il y a une autre valeur de 15?
David דודו Markovitz
@DuduMarkovitz Après 100 valeurs si aucune valeur de 16 n'a été trouvée, je voudrais recommencer à la prochaine 15 valeurs. S'il existe une autre valeur de 15 après moins de 100 valeurs, elle devrait recommencer. Pour mes besoins, cela devrait rarement arriver, voire pas du tout. C'est une question valable cependant.
Lien
Merci. heureusement, c'est ainsi que les solutions actuelles le gèrent.
David דודו Markovitz

Réponses:

7

Une suggestion qui devrait fonctionner dans la version 2008.

Testé sur 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  ;

Plus d'informations:

ypercubeᵀᴹ
la source
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)
David דודו Markovitz
la source
2
C'est en version 2008. Non COUNT(*) OVER (ORDER BY ..)autorisé.
ypercubeᵀᴹ
Ça a l'air génial et me fait réaliser que j'ai besoin de lire un peu plus pour comprendre ce que tout cela fait. Merci pour la contribution.
Lien du