【问题标题】:PL/SQL: INSTR(), SUBSTR(), How to extract values from multi-select-listPL/SQL: INSTR(), SUBSTR(), 如何从多选列表中提取值
【发布时间】: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 如果它在某处生产,它不会持续很长时间。

标签: sql oracle plsql oracle11g


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-01
    • 1970-01-01
    • 2015-08-30
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    相关资源
    最近更新 更多