Oracle生成2列数据​​之间的范围

时间:2015-04-01 23:50:08

标签: sql oracle

美好的一天,

我的表格如下所示

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

感谢您的帮助。

1 个答案:

答案 0 :(得分: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)。