Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Menggabungkan interval validitas tanggal yang berurutan

Ini adalah masalah kesenjangan dan pulau. Ada berbagai cara untuk mendekatinya; ini menggunakan lead dan lag fungsi analitik:

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

Kueri terdalam melihat catatan sebelumnya dan berikut untuk produk, dan hanya mempertahankan waktu mulai dan/atau berakhir jika catatan tidak bersebelahan:

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 

Tingkat pemilihan berikutnya menghapus yang merupakan periode pertengahan, di mana kedua tanggal dikosongkan oleh kueri dalam, yang memberikan:

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 

Kueri luar kemudian menciutkan pasangan yang berdekatan itu; Saya telah menggunakan rute mudah untuk membuat duplikat dan kemudian menghilangkannya dengan distinct , tetapi Anda dapat melakukannya dengan cara lain, seperti memasukkan kedua nilai ke dalam salah satu pasangan baris dan membiarkan kedua nilai di null lainnya, lalu menghilangkan nilai tersebut dengan lapisan pilih lainnya, tetapi menurut saya perbedaan tidak masalah di sini.

Jika kasus penggunaan dunia nyata Anda memiliki waktu, bukan hanya tanggal, maka Anda harus menyesuaikan perbandingan dalam kueri dalam; daripada +/- 1, interval 1 detik mungkin, atau 1/86400 jika Anda mau, tetapi tergantung pada ketepatan nilai Anda.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cari string tertentu di kolom Oracle clob

  2. Daftar pencarian Oracle kata-kata dalam string dan retruen yang sudah ada

  3. SaveOrUpdate Hibernate mengabaikan properti kolom bukan-null

  4. Panggilan getColumnName(0) sederhana melempar Indeks kolom tidak valid:getValidColumnIndex

  5. Prosedur Tersimpan Java Vs Prosedur Tersimpan PL/SQL