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

Posted

技术标签:

【中文标题】PL/SQL: INSTR(), SUBSTR(), 如何从多选列表中提取值【英文标题】:PL/SQL: INSTR(), SUBSTR(), How to extract values from multi-select-list 【发布时间】:2017-03-11 12:52:35 【问题描述】:

给出以下情况: 表 order o 和 products p 是通过多选列表连接的。

产品p:

主键 PRODUCT_ID 类似于“101” 商店购买价格如“9.25”

下单:

主键 ORDER_ID 类似于“123456” 将所有包含的产品存储在一个名为 prod 的列中,例如“:101:199:250:999:” 将所有包含的单价存储在名为“:10.0:25.0:30.5:125.25:”的列中

例如,订单 123456 包含四种产品。 id 101 的产品以10.0$ 出售(而购买价格为9.25$),id 199 的产品以25.0$ 出售等等......

所以对我来说最具挑战性的部分是从多选列表中提取所需的值。

如何根据订购的产品提取价格以回答诸如“id = 999 的产品的平均销售价格是多少?”之类的问题

我已经尝试过类似的方法:

SELECT MOD(INSTR(o.products, ':999:'),3)  FROM orders o;

返回值的位置。

由于我不是PL/SQL 程序员,我不知道如何继续处理这个问题...... 欢迎提出想法。

【问题讨论】:

您首先不应该将多个分隔值存储在单个列中。阅读数据库规范化 是的,我知道这一点......使用带有 order_id 和 product_id 键的第三个表会更有效。尽管如此,解决方案应该基于多选列表......:-/ 这行不通。我确信这方面的聪明人可以提供一些可行的功能代码;但是一旦你尝试扩展系统,就会出现问题。所以真正的答案是修复设计。 请告诉我这是一项学校作业,而不是某个正在生产的系统 @APC 如果它在某处生产,它不会持续很长时间。 【参考方案1】:

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

您要为两个以冒号分隔的具有相同数量的标记等的字符串承担责任(这是首先拥有正常形式的表格的 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

【讨论】:

以上是关于PL/SQL: INSTR(), SUBSTR(), 如何从多选列表中提取值的主要内容,如果未能解决你的问题,请参考以下文章

PL SQL oracle instr function|异常行为

正则表达式 substr,起始位置位于字符串 PL/SQL 的末尾

Oracle中的instr()函数和substr函数

超过 4000 个字符的 Substr 得到 ORA-06502: PL/SQL: numeric or value error

Oracle19instr()和substr()函数

oracle instr,substr 截取字符串