PL/SQL:INSTR(),SUBSTR(),如何从多选列表中提取值

PL/SQL:INSTR(),SUBSTR(),如何从多选列表中提取值,sql,oracle,plsql,oracle11g,Sql,Oracle,Plsql,Oracle11g,给出了以下情况: 订单o和产品p表通过多选列表连接 产品p: 主键产品\u ID类似于101 商店购买价格9.25美元 命令o: 主键顺序\u ID类似于123456 将所有包含的产品存储在一个名为prod like:101:199:250:999的列中: 在名为“价格”的列中存储所有包含的单价,如:10.0:25.0:30.5:125.25: 例如,订单123456包括四种产品。id为101的产品售价为10.0美元,而购买价格为9.25美元,id为199的产品售价为25.0美元,依此类推 因此

给出了以下情况: 订单o和产品p表通过多选列表连接

产品p:

主键产品\u ID类似于101 商店购买价格9.25美元 命令o:

主键顺序\u ID类似于123456 将所有包含的产品存储在一个名为prod like:101:199:250:999的列中: 在名为“价格”的列中存储所有包含的单价,如:10.0:25.0:30.5:125.25: 例如,订单123456包括四种产品。id为101的产品售价为10.0美元,而购买价格为9.25美元,id为199的产品售价为25.0美元,依此类推

因此,对我来说,最具挑战性的部分是从multiselect列表中提取所需的值

如何提取与订购产品相关的价格,以回答id=999的产品的平均销售价格是多少等问题

我已经试过这样的方法:

SELECT MOD(INSTR(o.products, ':999:'),3)  FROM orders o;
返回值的位置

由于我不是PL/SQL程序员,我不知道如何继续讨论这个问题。。。
欢迎提出意见。

您可以在更大的查询中使用下面的查询。或者,您可以使用它一次性地规范化数据。或者两者兼而有之

您将负责两个冒号分隔的字符串,它们具有相同数量的令牌等。这是将表设置为正常形式的100多个原因之一

with
     orders ( order_id, prod, prices ) as (
       select 123456, ':101:99:250:999:', ':10.0:25.0:30.5:125.25:' from dual union all
       select 1003  , ':101:999:'       , ':9.95:130.40:'           from dual
     )
select order_id,
       to_number(substr(prod, instr(prod, ':', 1, level) + 1, 
             instr(prod, ':', 1, level + 1) - instr(prod, ':', 1, level) - 1)) as prod_id,
       to_number(substr(prices, instr(prices, ':', 1, level) + 1, 
             instr(prices, ':', 1, level + 1) - instr(prices, ':', 1, level) - 1)) as price
from   orders
connect by level <= length(prod) - length(replace(prod, ':')) - 1
       and prior order_id = order_id
       and prior sys_guid() is not null
;

ORDER_ID  PROD_ID   PRICE
--------  -------  ------
    1003      101    9.95
    1003      999    30.4
  123456      101      10
  123456       99      25
  123456      250    30.5
  123456      999  125.25

首先,您不应该在单个列中存储多个分隔值。阅读数据库规范化是的,我知道这一点……使用第三个表,其中包含order_id和product_id键会更有效。不过,解决方案应该基于multiselect列表……:-/这不起作用。我相信这方面的聪明人可以提供一些可以工作的功能代码;但一旦你试图扩展这个系统,就会出现问题。所以,真正的答案是修复设计。请告诉我这是一个学校作业,而不是一个正在生产的系统somewhere@APC如果它在某个地方生产,不会持续太久。