指定された値から別の指定された値までの行を選択します


8

複数の列を含むテーブルがあり、列の値を確認したいのですが、別の列の値が表示されるまで、その列の値の後の行を選択します。私はを使用してみましたBETWEENが、列の値が整数の場合、整数間の数値のみを検索します。

たとえば、次のようなテーブルがあるとします。

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 3:00 PM 2
t8 3:05 PM 100
t2 7:00 PM 15
t2 7:01 PM 16
t15 5:00 AM 35 

15と16の値の間の行を取得したいと思います。基本的に、で並べ替えてid、が表示され、time15が表示された後、同じ内に値が16になるまで行を収集できますid。値16がない場合、たとえば次の100行が必要で、次の値15を検索します。

クエリがこれを返すようにします。

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 3:00 PM 2
t8 3:05 PM 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の値がある場合に、ソリューションでどのように処理しますか?
デビッドדודוマルコヴィッツ2016

@DuduMarkovitz 16の値が見つからない場合、100の値の後、次の15の値からやり直したいと思います。100未満の値の後に15の別の値がある場合は、最初からやり直す必要があります。私の目的では、これが発生することはほとんどありません。それは有効な質問です。
2016

ありがとう。幸い、これは現在のソリューションですでに処理されている方法です。
DavidדודוMarkovitz 2016

回答:


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ᵀᴹ

見栄えがよく、これが何をするのかを理解するためにもう少し読む必要があることに気付かされます。入力いただきありがとうございます。
リンク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.