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

Oracle SQL - Identifikasi rentang nilai berurutan

Ini mudah dilakukan dengan teknik yang disebut Tabibitosan.

Apa yang dilakukan teknik ini adalah membandingkan posisi setiap baris kelompok dengan kumpulan baris keseluruhan, untuk mengetahui apakah baris dalam kelompok yang sama bersebelahan atau tidak.

Misalnya, dengan data contoh Anda, ini terlihat seperti:

WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                    SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 6 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 7 ID, 'Kevin' NAME, 'Production' department FROM dual)
-- end of mimicking your table with data in it. See the SQL below:
SELECT ID,
       NAME,
       department,
       row_number() OVER (ORDER BY ID) overall_rn,
       row_number() OVER (PARTITION BY department ORDER BY ID) department_rn,
       row_number() OVER (ORDER BY ID) - row_number() OVER (PARTITION BY department ORDER BY ID) grp
FROM   your_table;

        ID NAME    DEPARTMENT OVERALL_RN DEPARTMENT_RN        GRP
---------- ------- ---------- ---------- ------------- ----------
         1 Michael Marketing           1             1          0
         2 Alex    Marketing           2             2          0
         3 Tom     Marketing           3             3          0
         4 John    Sales               4             1          3
         5 Brad    Marketing           5             4          1
         6 Leo     Marketing           6             5          1
         7 Kevin   Production          7             1          6

Di sini, saya telah memberikan semua baris di seluruh kumpulan data nomor baris dalam urutan id menaik (overall_rn kolom), dan saya telah memberikan nomor baris di setiap departemen (department_rn kolom), lagi dalam urutan id menaik.

Sekarang setelah saya selesai melakukannya, kita dapat mengurangi satu dari yang lain (grp kolom).

Perhatikan bagaimana nomor di kolom grp tetap sama untuk baris departemen yang bersebelahan, tetapi berubah setiap kali ada celah.

Misalnya. untuk bagian Pemasaran, baris 1-3 bersebelahan dan memiliki grp =0, tetapi baris Pemasaran ke-4 sebenarnya berada di baris ke-5 dari kumpulan hasil keseluruhan, jadi sekarang memiliki nomor grp yang berbeda. Karena baris pemasaran ke-5 berada di baris ke-6 dari kumpulan keseluruhan, baris tersebut memiliki nomor grp yang sama dengan baris pemasaran ke-4, jadi kita tahu bahwa baris tersebut bersebelahan.

Setelah kami memiliki informasi grp itu, mudah saja melakukan pengelompokan kueri agregat pada departemen dan kolom grp baru kami, menggunakan min dan max untuk menemukan id awal dan akhir:

WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                    SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 6 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 7 ID, 'Kevin' NAME, 'Production' department FROM dual)
-- end of mimicking your table with data in it. See the SQL below:
SELECT department,
       MIN(ID) start_id,
       MAX(ID) end_id
FROM   (SELECT ID,
               NAME,
               department,
               row_number() OVER (ORDER BY ID) - row_number() OVER (PARTITION BY department ORDER BY ID) grp
        FROM   your_table)
GROUP BY department, grp;

DEPARTMENT   START_ID     END_ID
---------- ---------- ----------
Marketing           1          3
Marketing           5          6
Sales               4          4
Production          7          7

N.B., saya berasumsi bahwa celah di kolom id tidak penting (yaitu jika tidak ada baris untuk id =6 (jadi id Leo dan Kevin masing-masing adalah 7 dan 8), maka Leo dan Brad akan tetap muncul di kolom yang sama grup, dengan id awal =5 dan id akhir =7.

Jika celah dalam kolom id dihitung sebagai indikasi grup baru, maka Anda bisa menggunakan id untuk memberi label pada kumpulan baris keseluruhan (yaitu tidak perlu menghitung overall_rn; cukup gunakan kolom id saja).

Itu berarti kueri Anda akan menjadi:

WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                    SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 7 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 8 ID, 'Kevin' NAME, 'Production' department FROM dual)
-- end of mimicking your table with data in it. See the SQL below:
SELECT department,
       MIN(ID) start_id,
       MAX(ID) end_id
FROM   (SELECT ID,
               NAME,
               department,
               ID - row_number() OVER (PARTITION BY department ORDER BY ID) grp
        FROM   your_table)
GROUP BY department, grp;

DEPARTMENT   START_ID     END_ID
---------- ---------- ----------
Marketing           1          3
Sales               4          4
Marketing           5          5
Marketing           7          7
Production          8          8


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara menampilkan hasil pernyataan SELECT yang dieksekusi menggunakan SQL dinamis asli?

  2. ORA-00054:sumber daya sibuk dan dapatkan dengan SEKARANG ditentukan atau batas waktu kedaluwarsa

  3. Bagaimana cara menyimpan string yang lebih panjang dari 4000 karakter dalam Oracle Database menggunakan Java/JDBC?

  4. Oracle dinamis DESC dan ASC diurutkan oleh

  5. penjumlahan sekuensial kueri Oracle per baris