Du kan gøre det ved at bruge ROW_NUMBER analytisk funktion. Se Find række af på hinanden følgende værdier i en række af tal eller datoer .
For eksempel
Rækkevidde
SQL> with data(num) as(
2 select 1 from dual union
3 select 2 from dual union
4 select 3 from dual union
5 select 5 from dual union
6 select 6 from dual union
7 select 7 from dual union
8 select 10 from dual union
9 select 11 from dual union
10 select 12 from dual union
11 select 20 from dual
12 )
13 select min(num)||'-'|| max(num) as "range"
14 from (select num,
15 num-Row_Number() over(order by num)
16 as rn
17 from data)
18 group by rn
19 order by min(num);
range
-------------------------------------------------
1-3
5-7
10-12
20-20
SQL>
Liste
SQL> with data(num) as(
2 select 1 from dual union
3 select 2 from dual union
4 select 3 from dual union
5 select 5 from dual union
6 select 6 from dual union
7 select 7 from dual union
8 select 10 from dual union
9 select 11 from dual union
10 select 12 from dual union
11 select 20 from dual
12 )
13 SELECT listagg(range, ',') WITHIN GROUP(
14 ORDER BY min_num) AS "list"
15 FROM
16 (SELECT MIN(num) min_num,
17 MIN(num)
18 ||'-'
19 || MAX(num) range
20 FROM
21 (SELECT num, num-Row_Number() over(order by num) AS rn FROM DATA
22 )
23 GROUP BY rn
24 );
list
-------------------------------------------------------------------------
1-3,5-7,10-12,20-20
SQL>
Opdater OP ønsker en løsning i PL/SQL til at gemme listen i en PL/SQL-variabel.
Opsætning
SQL> CREATE TABLE t AS
2 SELECT *
3 FROM
4 ( WITH data(num) AS
5 ( SELECT 1 FROM dual
6 UNION
7 SELECT 2 FROM dual
8 UNION
9 SELECT 3 FROM dual
10 UNION
11 SELECT 5 FROM dual
12 UNION
13 SELECT 6 FROM dual
14 UNION
15 SELECT 7 FROM dual
16 UNION
17 SELECT 10 FROM dual
18 UNION
19 SELECT 11 FROM dual
20 UNION
21 SELECT 12 FROM dual
22 UNION
23 SELECT 20 FROM dual
24 )
25 SELECT * FROM DATA);
Table created.
PL/SQL-blok
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 v_list VARCHAR2(100);
3 BEGIN
4 SELECT listagg(RANGE, ',') WITHIN GROUP(
5 ORDER BY min_num)
6 INTO v_list
7 FROM
8 (SELECT MIN(num) min_num,
9 MIN(num)
10 ||'-'
11 || MAX(num) range
12 FROM
13 (SELECT num, num-Row_Number() over(order by num) AS rn FROM t
14 )
15 GROUP BY rn
16 );
17 dbms_output.put_line(v_list);
18 END;
19 /
1-3,5-7,10-12,20-20
PL/SQL procedure successfully completed.
SQL>