Chọn các hàng bắt đầu từ giá trị được chỉ định cho đến khi giá trị được chỉ định khác


8

Tôi có một bảng chứa một số cột và muốn kiểm tra giá trị cột, chọn các hàng sau giá trị cột đó cho đến khi giá trị cột riêng biệt xuất hiện. Tôi đã thử sử dụng BETWEEN, nhưng nếu các giá trị cột là số nguyên thì nó chỉ tìm số giữa các số nguyên.

Ví dụ: nếu tôi có một bảng như thế này:

giá trị thời gian id 
t1 12:00 CH 15
t1 12:02 CH 4
t1 12:03 CH 7
t1 12:05 CH 16
t5 12:10 PM 250
t5 12:15 chiều 15
t8 11:00 sáng 15
t8 3:00 CH 2
t8 3:05 chiều 100
t2 7:00 tối 15
t2 7:01 16
t15 5:00 sáng 35 

Tôi muốn lấy các hàng giữa các giá trị 15 và 16. Về cơ bản, nếu tôi có thể sắp xếp theo id, sau đó time, và tập hợp các hàng sau 15 xuất hiện cho đến khi có giá trị 16 trong cùng một giá trị id. Nếu không có giá trị 16, tôi sẽ muốn 100 hàng tiếp theo chẳng hạn và sau đó tìm kiếm giá trị tiếp theo là 15.

Tôi muốn truy vấn để trả về điều này:

giá trị thời gian id 
t1 12:00 CH 15
t1 12:02 CH 4
t1 12:03 CH 7
t1 12:05 CH 16
t2 7:00 tối 15
t2 7:01 16
t5 12:15 chiều 15
t8 11:00 sáng 15
t8 3:00 CH 2
t8 3:05 chiều 100

Điều đó có thể gây nhầm lẫn. Tôi đã thử:

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

làm điểm bắt đầu, nhưng chỉ trả về các hàng có giá trị 15 hoặc 16 vì chúng là số nguyên.

Tôi muốn sắp xếp bảng theo idsau đó time. Các mục này được thêm tự động thông qua một hệ thống khác vì vậy tôi đang cố gắng truy vấn bảng cho các phạm vi giá trị cụ thể.

Có ý kiến ​​gì không?

Làm rõ:

Nếu tôi có các hàng 15, 1, 16, 7, 15, 2, 16giống nhau id, tôi sẽ muốn cả hai "đảo" : 15, 1, 16, 15, 2, 16.


Làm thế nào để bạn muốn giải pháp xử lý trường hợp 15 được tìm thấy và sau một số giá trị không phải là 16, có 15 giá trị khác?
David TOUR TOUR Markovitz

@DuduMarkovitz Sau 100 giá trị nếu không tìm thấy giá trị 16, tôi muốn bắt đầu lại ở 15 giá trị tiếp theo. Nếu có một giá trị khác là 15 sau ít hơn 100 giá trị, thì nó sẽ bắt đầu lại. Đối với mục đích của tôi, điều này hiếm khi xảy ra nếu có. Đó là một câu hỏi hợp lệ mặc dù.
Liên kết

Cảm ơn. may mắn thay, đây là cách nó đã được xử lý bởi các giải pháp hiện tại.
David TOUR TOUR Markovitz

Câu trả lời:


7

Một gợi ý nên hoạt động trong phiên bản 2008.

Đã thử nghiệm tại 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  ;

Thêm thông tin:


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
Đó là phiên bản 2008. Không COUNT(*) OVER (ORDER BY ..)được phép.
ypercubeᵀᴹ

Trông thật tuyệt và khiến tôi nhận ra mình cần đọc thêm một chút để hiểu tất cả những điều này làm gì. Cảm ơn các đầu vào.
Liên kết
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.