美好的一天,
我的表格如下所示
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
感谢您的帮助。
答案 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)。