Sql 如何获取字符串,将其中的小数转换为小数,提取字符串的一部分,并将其与表进行比较?

Sql 如何获取字符串,将其中的小数转换为小数,提取字符串的一部分,并将其与表进行比较?,sql,oracle12c,Sql,Oracle12c,以下是我需要解析的数据: --TABLE: PRICE_LIST ITEM_DESCRIPTION VARCHAR2(60) VENDOR_PARTNO VARCHAR2(15) ---------------------------- -------------------------- .374 x 3 w/ph KLT-6 5506125 .4375 x 3-1/2 w/ph KLT-3345 5506124 .125 x 2-1/2 w/ph KLT

以下是我需要解析的数据:

--TABLE: PRICE_LIST


ITEM_DESCRIPTION VARCHAR2(60)  VENDOR_PARTNO VARCHAR2(15)
----------------------------   --------------------------
.374 x 3 w/ph KLT-6            5506125
.4375 x 3-1/2 w/ph KLT-3345    5506124
.125 x 2-1/2 w/ph KLT-3211     5506123
.3125 x 4-1/2 w/ph KUR-44      5506127
这是我需要比较价目表项目描述的表格:

--Table: MATERIALS
--COLUMN: VARCHAR2(20)

ITEM_ID 
--------------
1/2 X 3-1/2
5/16 X 4-1/2
1/8 X 2-1/2
我尝试了这种方法,试图将它们分开,但这需要做很多工作:

SELECT SUBSTR(VALUE, 1, INSTR(VALUE, 'x')-1) DIAMETER,
       SUBSTR(VALUE, INSTR(VALUE, 'x')+1) DIRTY_LENGTH
       FROM (SELECT DESCRIPTION VALUE FROM PRICE_LIST);

DIAMETER    DIRTY_LENGTH
--------    ------------
.374        3 w/ph KLT-6
.4375       3-1/2 w/ph KLT-3345
.125        2-1/2 w/ph KLT-3211
.3125       4-1/2 w/ph KUR-44
但现在我有一个带小数的列,我不知道该怎么处理,还有一个列有我的第二个小数,但其他数据我不需要

因为只有PRICE_LIST表中的最后两个值匹配,所以我只想返回以下值:

ITEM_DESCRIPTION   VENDOR_PARTNO
----------------   -------------
1/8 X 2-1/2        5506123
5/16 X 4-1/2       5506127

谢谢你的帮助

数据格式很糟糕。似乎需要创建自定义的用户定义PL/SQL函数来计算这些表达式:

CREATE OR REPLACE FUNCTION evaluate_me( p_x VARCHAR2 )
RETURN NUMBER
DETERMINISTIC
IS
  x VARCHAR2( 200 );
  expr VARCHAR2(100);
  y NUMBER;
BEGIN
  x := lower( substr( p_x, 1, regexp_instr( p_x ||'q', '[^.0-9 xX\/\-]+' )-1));
  expr := replace( 'BEGIN :p:='|| x ||'; END;', 'x', '*' );
  execute immediate expr USING OUT y;
  RETURN y;
END;
/
然后像这个例子一样:



这可能会非常慢,将为左表的每一行调用该函数,然后为右表的每一行调用该函数。因此,如果左表有10000行,右表有20000行(对于RDBMS系统来说不是那么多),那么函数将被调用10000+10000*20000=200010000次
这是一个糟糕设计的代价-数据不符合的规则,必须在每次访问时进行分析。

为了加快查询速度,您必须创建两个功能索引,否则启动此查询时,您可以每月休假一次:

CREATE INDEX MATERIALS_eval ON MATERIALS( evaluate_me( ITEM_ID ) );

CREATE INDEX PRICE_LIST_eval ON PRICE_LIST( evaluate_me( ITEM_DESCRIPTION ));

为什么要使用设计如此糟糕的数据?您应该有一个可以用来匹配的主键,而不是处理格式错误的数据和草率的字符串解析和比较。你可能想买一本书或找一本关于基本数据库设计原则的网络教程。看起来描述的第一部分可能对应于直径(.125==1/4等)。是的,数据应该是结构化的。目前它很难理解和使用。@KenWhite-我不知道OP的具体情况。但是,你能想象这样一种情况吗?这是现有的数据,在一个意识到他们以前的IT人员是多么愚蠢的组织中(只看数据模型),他们解雇了所有那些不称职的人,而是雇佣OP和其他人来处理混乱?当然,修复数据模型等。您将如何做到这一点?你不需要完全按照OP的要求去做吗?如果你需要帮助,你会在这里问吗?@Bohemian-如果你能解释这个问题有什么不清楚或“太宽泛”的地方,那会有帮助。这对我来说是非常清楚的,可能对许多与Oracle或一般数据库合作的人来说也是如此。也许你(和肯·怀特)不清楚;这将有助于理解不清楚的地方。@mathguy:我将创建一个包含两个匹配值的主键的中间表。查找其中一个来查找匹配项,并将键作为ID处理。我当然不会试图解析文本来查找浮点数,以尝试转换为片段来进行文本比较。感谢您花时间发布此内容。明天我会在办公室测试一下,然后再传回来。我同意数据是一团糟。它的设计很差,并以这种方式维护了15年。
select m.*, evaluate_me( item_id ) x
from MATERIALS m
;
|      ITEM_ID |     X |
|--------------|-------|
|  1/2 X 3-1/2 |     1 |
| 5/16 X 4-1/2 |  0.75 |
|  1/8 X 2-1/2 | -0.25 |
SELECT *
FROM PRICE_LIST p
JOIN MATERIALS m
ON evaluate_me( p.item_description ) = evaluate_me( m.item_id )
;

|           ITEM_DESCRIPTION | VENDOR_PARTNO |      ITEM_ID |
|----------------------------|---------------|--------------|
| .125 x 2-1/2 w/ph KLT-3211 |       5506123 |  1/8 X 2-1/2 |
|  .3125 x 4-1/2 w/ph KUR-44 |       5506127 | 5/16 X 4-1/2 |
CREATE INDEX MATERIALS_eval ON MATERIALS( evaluate_me( ITEM_ID ) );

CREATE INDEX PRICE_LIST_eval ON PRICE_LIST( evaluate_me( ITEM_DESCRIPTION ));