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

Bagaimana cara menemukan jumlah hari yang digunakan dalam sebulan?

Data Uji :

CREATE TABLE your_table ( usr, start_date, end_date ) AS (
  SELECT 'A', DATE '2017-06-01', DATE '2017-06-03' FROM DUAL UNION ALL
  SELECT 'B', DATE '2017-06-02', DATE '2017-06-04' FROM DUAL UNION ALL -- Overlaps previous
  SELECT 'C', DATE '2017-06-06', DATE '2017-06-06' FROM DUAL UNION ALL
  SELECT 'D', DATE '2017-06-07', DATE '2017-06-07' FROM DUAL UNION ALL -- Adjacent to previous
  SELECT 'E', DATE '2017-06-11', DATE '2017-06-20' FROM DUAL UNION ALL
  SELECT 'F', DATE '2017-06-14', DATE '2017-06-15' FROM DUAL UNION ALL -- Within previous
  SELECT 'G', DATE '2017-06-22', DATE '2017-06-25' FROM DUAL UNION ALL
  SELECT 'H', DATE '2017-06-24', DATE '2017-06-28' FROM DUAL UNION ALL -- Overlaps previous and next
  SELECT 'I', DATE '2017-06-27', DATE '2017-06-30' FROM DUAL UNION ALL
  SELECT 'J', DATE '2017-06-27', DATE '2017-06-28' FROM DUAL;          -- Within H and I          

Kueri :

SELECT SUM( days ) AS total_days
FROM   (
  SELECT dt - LAG( dt ) OVER ( ORDER BY dt ) + 1 AS days,
         start_end
  FROM   (
    SELECT dt,
           CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
             WHEN 1 THEN 'start'
             WHEN 0 THEN 'end'
           END AS start_end
    FROM   your_table
    UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
  )
  WHERE start_end IS NOT NULL
)
WHERE start_end = 'end';

Keluaran :

TOTAL_DAYS
----------
        25

Penjelasan :

SELECT dt, value
FROM   your_table
UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )

Ini akan UNPIVOT tabel sehingga tanggal mulai dan tanggal berakhir berada di kolom yang sama (dt ) dan diberi nilai +1 yang sesuai untuk tanggal mulai dan -1 untuk tanggal akhir.

SELECT dt,
       SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) AS total,
       value
FROM   your_table
UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )

Akan memberikan tanggal mulai dan berakhir dan jumlah kumulatif dari nilai-nilai yang dihasilkan. Awal rentang akan selalu memiliki value=1 dan total=1 dan akhir rentang akan selalu memiliki total=0 . Jika tanggal berada di pertengahan rentang, maka tanggal tersebut akan memiliki total>1 atau value=-1 dan total=1 . Menggunakan ini, jika Anda mengalikan value dan total maka awal rentang adalah ketika value*total=1 dan akhir rentang adalah saat value*total=0 dan nilai lainnya menunjukkan tanggal yang berada di tengah rentang.

Inilah yang memberi ini:

SELECT dt,
       CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
         WHEN 1 THEN 'start'
         WHEN 0 THEN 'end'
       END AS start_end
FROM   your_table
UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )

Anda kemudian dapat memfilter tanggal saat start_end adalah NULL yang akan memberi Anda tabel dengan start . bergantian dan end baris yang dapat Anda gunakan LAG untuk menghitung jumlah perbedaan hari:

SELECT dt - LAG( dt ) OVER ( ORDER BY dt ) + 1 AS days,
       start_end
FROM   (
  SELECT dt,
         CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
           WHEN 1 THEN 'start'
           WHEN 0 THEN 'end'
         END AS start_end
  FROM   your_table
  UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
)
WHERE start_end IS NOT NULL

Yang perlu Anda lakukan adalah SUM semua perbedaan untuk end - start; yang memberikan kueri di atas.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. periode batas waktu berlalu. semua koneksi yang dikumpulkan sedang digunakan dan ukuran kumpulan maksimum tercapai

  2. Cara menghitung kemunculan pemisah dalam string tidak termasuk yang ada dalam tanda kutip

  3. Tidak ada modul oci8 di phpinfo()

  4. Bagaimana menghindari kesalahan ORA-04091 dalam pemicu

  5. Oracle - perbarui bergabung - tabel tanpa kunci yang diawetkan