Oracle SQL - 字段中每个连接列表ID的返回值

时间:2017-03-28 19:24:38

标签: sql oracle

我正在使用Oracle 11g数据库。我有一个Items表,其中包含一个表示Item的相关产品的字段。 products字段中的数据可能包含也可能不包含以逗号分隔的连接值列表,其中每个值对应于包含产品名称的备用查找表中的产品ID。如果产品字段中至少有一个产品值,则该字段将以逗号开头并以逗号结束。

ITEM TABLE
╔══════╦═══════════════════╗
║ ITEM ║ PRODUCTS          ║
╠══════╬═══════════════════╣
║ 12   ║ ,101,102,103,     ║
║ 34   ║ ,103,105,         ║
║ 56   ║ ,101,102,104,105, ║
║ 78   ║                   ║
║ 90   ║ ,102,             ║
╚══════╩═══════════════════╝

PRODUCTS TABLE
╔════════════╦══════╗
║ PRODUCT_ID ║ NAME ║
╠════════════╬══════╣
║ 101        ║ PA   ║
║ 102        ║ PB   ║
║ 103        ║ PC   ║
║ 104        ║ PD   ║
║ 105        ║ PE   ║
╚════════════╩══════╝

我的目标是做一个SELECT查询,通过竖线获取带有连接产品名称的Items列表,但我不知道如何到达那里。

DESIRED RESULT
╔══════╦═════════════╗
║ ITEM ║ PRODUCTS    ║
╠══════╬═════════════╣
║ 12   ║ PA|PB|PC    ║
║ 34   ║ PC|PE       ║
║ 56   ║ PA|PB|PD|PE ║
║ 78   ║             ║
║ 90   ║ PB          ║
╚══════╩═════════════╝

感谢任何帮助或指导。

2 个答案:

答案 0 :(得分:0)

逗号分隔值不是存储数据的正确方法。考虑规范化架构。

您可以做的是首先使用分层connect by将逗号分隔列表转换为单独的行,然后将结果与products表连接,最后使用listagg将产品名称聚合回|分隔值。

select i.item,
    listagg(p.name, '|') within group (order by p.product_id) as products
from (
    select item,
        regexp_substr(trim(',' from products), '[^,]+', 1, level) as product_id
    from item connect by prior item = item
        and level <= regexp_count(trim(',' from products), ',') + 1
        and prior sys_guid() is not null
    ) i
left join products p on i.product_id = p.product_id
group by i.item;

产地:

ITEM    PRODUCTS
-------------------
12      PA|PB|PC
34      PC|PE
56      PA|PB|PD|PE
78      
90      PB

Demo

答案 1 :(得分:0)

首先,您需要拆分此逗号分隔的字符串,并将各个字符串作为行。使用这个:

select distinct ITEM_ID
        ,regexp_substr(PRODUCTS, '[^,]+', 1, level) PRODUCT_ID
    from item connect by regexp_substr(PRODUCTS, '[^,]+', 1, level) is not null

将上述查询用作表格,您可以加入主表。

select I.ITEM_ID
    ,P.PRODUCT_NAME
from ITEM I
inner join (
    select distinct ITEM_ID
        ,regexp_substr(PRODUCTS, '[^,]+', 1, level) PRODUCT_ID
    from item connect by regexp_substr(PRODUCTS, '[^,]+', 1, level) is not null
    ) X on X.ITEM_ID = I.ITEM_ID
inner join PRODUCTS P on P.PRODUCT_ID = X.PRODUCT_ID