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 ));