我正在使用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 ║ ╚══════╩═════════════╝
感谢任何帮助或指导。
答案 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
答案 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