Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Kết hợp các khoảng thời gian hiệu lực ngày liên tiếp với nhau

Đây là một vấn đề về khoảng cách và các đảo. Có nhiều cách khác nhau để tiếp cận nó; cái này sử dụng leadlag chức năng phân tích:

select distinct product,
  case when start_date is null then lag(start_date)
    over (partition by product order by rn) else start_date end as start_date,
  case when end_date is null then lead(end_date)
    over (partition by product order by rn) else end_date end as end_date
from (
  select product, start_date, end_date, rn
  from (
    select t.product,
      case when lag(end_date)
          over (partition by product order by start_date) is null
        or lag(end_date)
          over (partition by product order by start_date) != start_date - 1
        then start_date end as start_date,
      case when lead(start_date)
          over (partition by product order by start_date) is null
        or lead(start_date)
          over (partition by product order by start_date) != end_date + 1
        then end_date end as end_date,
      row_number() over (partition by product order by start_date) as rn
    from t
  )
  where start_date is not null or end_date is not null
)
order by start_date, product;

PRODUCT START_DATE END_DATE
------- ---------- ---------
A       01-JUL-13  30-SEP-13 
B       01-OCT-13  30-NOV-13 
A       01-DEC-13  31-MAR-14 

SQL Fiddle

Truy vấn trong cùng xem xét các bản ghi trước và sau cho sản phẩm và chỉ giữ lại thời gian bắt đầu và / hoặc kết thúc nếu các bản ghi không liền nhau:

select t.product,
  case when lag(end_date)
      over (partition by product order by start_date) is null
    or lag(end_date)
      over (partition by product order by start_date) != start_date - 1
    then start_date end as start_date,
  case when lead(start_date)
      over (partition by product order by start_date) is null
    or lead(start_date)
      over (partition by product order by start_date) != end_date + 1
    then end_date end as end_date
from t;

PRODUCT START_DATE END_DATE
------- ---------- ---------
A       01-JUL-13            
A                            
A                  30-SEP-13 
A       01-DEC-13            
A                            
A                            
A                  31-MAR-14 
B       01-OCT-13            
B                  30-NOV-13 

Cấp độ lựa chọn tiếp theo sẽ loại bỏ những ngày ở giữa khoảng thời gian, trong đó cả hai ngày đều bị truy vấn bên trong để trống, điều này mang lại:

PRODUCT START_DATE END_DATE
------- ---------- ---------
A       01-JUL-13            
A                  30-SEP-13 
A       01-DEC-13            
A                  31-MAR-14 
B       01-OCT-13            
B                  30-NOV-13 

Sau đó, truy vấn bên ngoài sẽ thu gọn các cặp liền kề đó; Tôi đã sử dụng cách dễ dàng để tạo các bản sao và sau đó loại bỏ chúng bằng distinct , nhưng bạn có thể làm theo những cách khác, chẳng hạn như đặt cả hai giá trị vào một trong các cặp hàng và để cả hai giá trị ở giá trị khác rỗng, sau đó loại bỏ những giá trị đó bằng một lớp chọn khác, nhưng tôi nghĩ việc phân biệt là OK ở đây.

Nếu trường hợp sử dụng trong thế giới thực của bạn có thời gian, không chỉ ngày, thì bạn sẽ cần điều chỉnh so sánh trong truy vấn bên trong; thay vì +/- 1, khoảng thời gian có thể là 1 giây hoặc 1/86400 nếu bạn thích, nhưng phụ thuộc vào độ chính xác của các giá trị của bạn.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để chuyển đổi câu lệnh nối bên ngoài bên trái kế thừa trong Oracle?

  2. Oracle- Chuỗi phân tách được phân cách bằng dấu phẩy (chuỗi chứa khoảng trắng và dấu phẩy liên tiếp)

  3. Trình tối ưu hóa sql cho Bảng Db Lớn

  4. Chèn dữ liệu vào cơ sở dữ liệu oracle bằng php

  5. Tại sao việc kiểm tra mảng kết hợp rỗng trong PL / SQL này không thành công?