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