2017-07-26 2 views
1

Ich schreibe eine Abfrage, die Zahlen zwischen angegebenen Bereichen generieren.Generieren Sie Zahlen für bestimmte Bereiche (SQL-Abfrage)

Ich habe eine Tabelle

NUM_RANGES 

ID START_NUMBER END_NUMBER 
-- ------------ ---------- 
1    1   5 
2    6   10 

Ich brauche dieses Ergebnis zu erhalten:

ID NUMBER 
    -- ------ 
    1  1 
    1  2 
    1  3 
    1  4 
    1  5 
    2  6 
    2  7 
    2  8 
    2  9 
    2  10 

Mit dieser Abfrage i richtiges Ergebnis bekommen, aber nur für bestimmte ID in where-Klausel:

select id, start_number + level - 1 next_tag 
         from (select id, start_number,end_number 
         from NUM_RANGES 
         where id = 1 
     ) 
     connect by level <= end_number - start_number + 1 

Ohne "where id = 1" bekomme ich 62 Zeilen mit Duplikaten, wobei distinct hilft, aber mit größeren Bereichen 1 - 200, 200- 500 es funktioniert zu langsam ..

Danke für Hilfe!

+0

Wie hoch muss Ihre end_number gehen? – RBarryYoung

Antwort

0

Auf Oracle 12c können Sie CROSS verwenden GILT:

select * 
from num_ranges 
cross apply(
    select level - 1 + start_number as my_new_number 
    from dual 
    connect by level <= end_number - start_number + 1 
); 
0

In Oracle 11.2 und früher Sie eine hierarchische Abfrage verwenden können:

with 
    num_ranges (id, start_number, end_number) as (
     select 1, 1, 5 from dual union all 
     select 2, 9, 12 from dual 
    ) 
-- End of simulated input data (for testing purposes only, not part of the solution). 
-- SQL query begins below this line. 
select  id, start_number + level - 1 as nmbr 
from  num_ranges 
connect by level <= end_number - start_number + 1 
     and prior id = id 
     and prior sys_guid() is not null 
order by id, nmbr -- If needed 
; 

     ID  NMBR 
---------- ---------- 
     1   1 
     1   2 
     1   3 
     1   4 
     1   5 
     2   9 
     2   10 
     2   11 
     2   12 

Insbesondere ohne neue Zeilen Anbindung an bestehende durch das gleiche id, erzeugen Sie eine wahnsinnige Anzahl unnötiger Zeilen. Deshalb benötigen Sie prior id = id. Die zusätzliche Bedingung prior sys_guid() is not null wird benötigt, damit Oracle keine Zyklen sieht, in denen es nicht angezeigt werden sollte (die genau durch "prior id = id" verursacht werden).

In Oracle 12.1 oder höher, können Sie die lateral-Klausel verwenden:

select n.id, l.nmbr 
from  num_ranges n, 
     lateral (select start_number + level - 1 as nmbr from dual 
        connect by level <= end_number - start_number + 1) l 
order by id, nmbr -- If needed 
; 
0

Diese funktionieren sollte. Ziemlich schnell auch.

with cte as (select 0 as c from dual) 
, cte4 as (select c from cte union all select c from cte union all select c from cte union all select c from cte) 
, cte256 as (select t0.c from cte4 t0, cte4 t1, cte4 t2, cte4 t3) 
, nums as (select row_number() over(order by null) as n from cte256 t0, cte256 t1, cte256 t2) 
select NR.id, nums.n as NUMBER_ 
from nums 
join NUM_RANGES NR on nums.n between NR.START_NUMBER and NR.END_NUMBER 
; 
Verwandte Themen