2015-04-01 2 views
1

Добрый день Все,Oracle генерировать диапазон между 2 столбцов данных

Я таблица структурированы, как показано ниже

f_number act_date amount range_start  range_end 
------------------------------------------------------------- 
T18564  20140702  10 700102180211 700102195210 
T18564  20140702  10 700104371331 700104376330 
T18564  20140702  20 700250037215 700250077214 
T18564  20140702  30 600311039928 600311044927 

Как генерировать все числа между диапазонами, так что мои данные отображаются в виде ,

f_number act_date amount item_id 
-------------------------------------------- 
T18564  20140702  10 700102180211  
           ... 
T18564  20140702  10 700102195210 
T18564  20140702  10 700104371331 
           ... 
T18564  20140702  10 700104376330 

и пр. Я попытался использовать,

select f_number, act_date, amount, to_number(range_start - 1) + level as item_id 
    from table 
connect by level <= (to_number(range_end) - to_number(range_start)) + 1 

, но он работает нормально для первого диапазона, после чего идет не так.

* to_number используется потому, что диапазоны сохраняются как varchar2

Спасибо за любую помощь.

ответ

2

Я думаю, что для эффективного использования CONNECT BY вам необходимо идентифицировать каждую строку однозначно. Я не вижу в ваших данных первичного ключа или уникального идентификатора (и хранят ли вы числа и даты в столбцах VARCHAR2? Плохая идея). Таким образом, вы можете попробовать что-то вроде этого:

WITH t1 AS (
    SELECT 'T18564' AS f_number, '20140702' AS act_date 
     , 10 AS amount, '700102180211' AS range_start 
     , '700102195210' AS range_end 
     FROM dual 
    UNION ALL 
    SELECT 'T18564', '20140702', 10, '700104371331', '700104376330' 
     FROM dual 
    UNION ALL 
    SELECT 'T18564', '20140702', 20, '700250037215', '700250077214' 
     FROM dual 
    UNION ALL 
    SELECT 'T18564', '20140702', 30, '600311039928', '600311044927' 
     FROM dual 
) 
SELECT f_number, act_date, amount, range_start - 1 + LEVEL 
    FROM (
    SELECT f_number, act_date, amount 
     , TO_NUMBER(range_start) AS range_start 
     , TO_NUMBER(range_end) AS range_end 
     , ROW_NUMBER() OVER (ORDER BY NULL) AS rn 
     FROM t1 
) CONNECT BY range_start - 1 + LEVEL <= range_end 
     AND PRIOR rn = rn 
     AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL; 

Обратите внимание, что я использую ROW_NUMBER() для создания уникального идентификатора строки. Вы также можете использовать что-то вроде SYS_GUID(), если вы были склонны (в этом случае порядок не должен иметь значения).

Я побежал выше в Oracle 10g, и он вернул правильное количество строк (в этом случае 65000 - сумма range_end - range_start + 1).

+0

Блестящий и спасибо за добавленную стоимость в ответ. У меня было 129 диапазонов для работы; Notepad ++ упростил форматирование для этого запроса. – jasmaar

Смежные вопросы