Wählen Sie Zeilen ab dem angegebenen Wert bis zu einem anderen angegebenen Wert aus

8

Ich habe eine Tabelle mit mehreren Spalten und möchte nach einem Spaltenwert suchen. Wählen Sie die Zeilen nach diesem Spaltenwert aus, bis ein separater Spaltenwert angezeigt wird. Ich habe versucht, zu verwenden BETWEEN, aber wenn die Spaltenwerte Ganzzahlen sind, sucht es nur nach Zahlen zwischen den Ganzzahlen.

Zum Beispiel, wenn ich eine Tabelle wie diese habe:

ID-Zeitwert 
t1 12:00 PM 15
t1 12:02 PM 4
t1 12:03 PM 7
t1 12:05 Uhr 16
t5 12:10 Uhr 250
t5 12:15 PM 15
t8 11:00 Uhr 15
t8 15:00 Uhr 2
t8 15:05 Uhr 100
t2 19:00 Uhr 15
t2 7:01 PM 16
t15 5:00 Uhr 35 

Ich mag die Zeilen zwischen Werten von 15 und 16 grundsätzlich bekommen, wenn ich von sortieren könnte id, dann time, und sammle die Reihen nach 15 erscheint , bis ein Wert von 16 innerhalb derselben ist id. Wenn es keinen Wert 16 gibt, würde ich zum Beispiel die nächsten 100 Zeilen wollen und dann nach dem nächsten Wert von 15 suchen.

Ich möchte, dass die Abfrage Folgendes zurückgibt:

ID-Zeitwert 
t1 12:00 PM 15
t1 12:02 PM 4
t1 12:03 PM 7
t1 12:05 Uhr 16
t2 19:00 Uhr 15
t2 7:01 PM 16
t5 12:15 PM 15
t8 11:00 Uhr 15
t8 15:00 Uhr 2
t8 15:05 Uhr 100

Das kann verwirrend sein. Ich habe es versucht:

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

als Ausgangspunkt, aber das gibt nur Zeilen mit Werten von 15 oder 16 zurück, weil sie ganze Zahlen sind.

Ich möchte die Tabelle bis iddahin sortieren time. Diese Einträge werden automatisch über ein anderes System hinzugefügt, daher versuche ich, die Tabelle nach bestimmten Wertebereichen abzufragen.

Irgendwelche Ideen?

Klärung:

Wenn ich Reihen mit 15, 1, 16, 7, 15, 2, 16dem gleichen hätte id, würde ich beide "Inseln" wollen : 15, 1, 16, 15, 2, 16.

Verknüpfung
quelle
Wie soll die Lösung mit einem Fall umgehen, in dem eine 15 gefunden wurde und nach einigen Werten, die nicht 16 sind, ein weiterer 15-Wert vorliegt?
David Markovitz
@DuduMarkovitz Nach 100 Werten, wenn kein Wert von 16 gefunden wurde, möchte ich bei den nächsten 15 Werten neu beginnen. Wenn nach weniger als 100 Werten ein anderer Wert von 15 angezeigt wird, sollte dieser erneut gestartet werden. Für meine Zwecke sollte dies selten oder gar nicht passieren. Es ist jedoch eine gültige Frage.
Link
Vielen Dank. Zum Glück wird dies bereits von den aktuellen Lösungen so gehandhabt.
David Markovitz

Antworten:

7

Ein Vorschlag, der in der Version 2008 funktionieren sollte.

Getestet bei 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  ;

Mehr Info:

ypercubeᵀᴹ
quelle
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
quelle
2
Es ist in der Version 2008. Nein COUNT(*) OVER (ORDER BY ..)erlaubt.
Ypercubeᵀᴹ
Sieht gut aus und macht mir klar, dass ich etwas mehr lesen muss, um zu verstehen, was das alles bewirkt. Danke für die Eingabe.
Link