根据另一列的值,通过分号将列值拆分为单独的行

时间:2021-06-10 17:34:06

标签: sql oracle oracle11g

我需要根据数量值生成行。

条码列的值由分号“;”分隔 我想将每个分隔值转换为单独的列。

如果条码值小于数量,条码列的其他行将为空。条码值不会超过数量。

| Name         | Quantity    | Barcode
+--------------+-------------+-----------------------------
| Apple        | 5           | barcode1;barcode2;barcode3

预期输出:

| Name         | Barcode
+--------------+----------
| Apple        | barcode1
| Apple        | barcode2
| Apple        | barcode3
| Apple        | 
| Apple        | 

Example data

3 个答案:

答案 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;

db<>fiddle

答案 2 :(得分:1)

您可以使用以下代码来获得所需的结果 -

SELECT name, regexp_substr(barcode,'[^;]+',1,level) as barcode
  FROM T
CONNECT BY LEVEL <= quantity;

这是fiddle

相关问题