我需要根据数量值生成行。
条码列的值由分号“;”分隔 我想将每个分隔值转换为单独的列。
如果条码值小于数量,条码列的其他行将为空。条码值不会超过数量。
| Name | Quantity | Barcode
+--------------+-------------+-----------------------------
| Apple | 5 | barcode1;barcode2;barcode3
预期输出:
| Name | Barcode
+--------------+----------
| Apple | barcode1
| Apple | barcode2
| Apple | barcode3
| Apple |
| Apple |
答案 0 :(得分:3)
您可以使用 CROSS JOIN
来拆分字符串,即使表格中有多行,仍然可以获得正确的行数。
WITH
fruit (name, quantity, barcode)
AS
(SELECT 'Apple', 5, 'barcode1;barcode2;barcode3' FROM DUAL
UNION ALL
SELECT 'Banana', 4, 'A;B;C' FROM DUAL)
SELECT f.name, s.COLUMN_VALUE AS barcode
FROM fruit f
CROSS JOIN
TABLE (CAST (MULTISET ( SELECT REGEXP_SUBSTR (f.barcode,
'[^;]+',
1,
LEVEL)
FROM DUAL
CONNECT BY LEVEL <= f.quantity) AS SYS.OdciVarchar2List)) s;
答案 1 :(得分:2)
如果您一次拆分多个源行,则连接方法需要条件以防止交叉匹配;所以你可以这样做:
select name, regexp_substr(barcode, '(.*?)(;|$)', 1, level, null, 1)
from your_table
connect by name = prior name
and prior sys_guid() is not null
and level <= quantity;
由于您使用的是 11g,并且假设它是 11gR2,您还可以使用递归 CTE:
with rcte (name, pos, barcode, quantity, all_barcodes) as (
select name, 1, regexp_substr(barcode, '(.*?)(;|$)', 1, 1, null, 1), quantity, barcode
from your_table
union all
select name, pos + 1, regexp_substr(all_barcodes, '(.*?)(;|$)', 1, pos + 1, null, 1), quantity, all_barcodes
from rcte
where pos < quantity
)
select name, barcode
from rcte
order by name, pos;
答案 2 :(得分:1)
您可以使用以下代码来获得所需的结果 -
SELECT name, regexp_substr(barcode,'[^;]+',1,level) as barcode
FROM T
CONNECT BY LEVEL <= quantity;
这是fiddle。