选择从指定值开始直到另一个指定值的行


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,然后time在15出现之后收集行,直到在same内存在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需要两个“ islands” :15, 1, 16, 15, 2, 16


您希望解决方案如何处理发现15的情况,并且在某些非16的值之后还有另一个15的值?
DavidדודוMarkovitz

@DuduMarkovitz如果没有找到16个值,则在100个值之后,我想从下一个15个值重新开始。如果小于100的值后还有另一个15的值,则应重新开始。就我的目的而言,这种情况很少发生。这是一个有效的问题。
链接

谢谢。幸运的是,这是当前解决方案已经处理的方式。
DavidדודוMarkovitz

Answers:


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

看起来很棒,让我意识到我需要阅读更多内容才能理解所有这些功能。感谢您的输入。
链接
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.