【问题标题】:Oracle SQL - Return value for each concatenated list ID in fieldOracle SQL - 字段中每个连接列表 ID 的返回值
【发布时间】:2017-03-28 19:24:38
【问题描述】:

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

项目表 ╔══════╦═══════════════════╗ ║ 项目 ║ 产品 ║ ╠══════╬═══════════════════╣ ║ 12 ║ ,101,102,103, ║ ║ 34 ║ ,103,105, ║ ║ 56 ║ ,101,102,104,105, ║ ║ 78 ║ ║ ║ 90 ║ ,102, ║ ╚══════╩═══════════════════╝ 产品表 ╔════════════╦══════╗ ║ PRODUCT_ID ║ 名称 ║ ╠════════════╬══════╣ ║101║PA║ ║ 102 ║ 铅 ║ ║ 103 ║ 电脑 ║ ║104║PD║ ║ 105 ║ 体育 ║ ╚════════════╩══════╝

我的目标是执行 SELECT 查询,以通过垂直条获取项目列表及其串联的产品名称,但我不知道如何到达那里。

期望的结果 ╔══════╦═════════════╗ ║ 项目 ║ 产品 ║ ╠══════╬═════════════╣ ║ 12 ║ PA|PB|PC ║ ║ 34 ║ 个人电脑|体育 ║ ║ 56 ║ PA|PB|PD|PE ║ ║ 78 ║ ║ ║ 90 ║ 铅 ║ ╚══════╩═════════════╝

感谢任何帮助或指导。

【问题讨论】:

  • 这是一个错误的数据库设计。您不应该在表格中使用逗号分隔的值,这违反了规范化。您的表格甚至不是第一范式。
  • @apatto03 - 您使用的是哪个版本的 Oracle?
  • 理解并同意;它不是来自我们设计或控制的数据库。
  • @GurV Oracle DB 11.2.0.3.0

标签: sql oracle


【解决方案1】:

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

您可以首先使用分层connect by 将逗号分隔列表转换为单独的行,然后将结果与产品表连接,最后使用 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

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

    • 您的连接方式将无法正常工作超过一行。
    猜你喜欢
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 2010-10-17
    • 1970-01-01
    相关资源
    最近更新 更多