2017-11-18 82 views
1

这是我需要分析的数据:如何取一个字符串,将小数内的小数转换为分数,提取部分字符串,并将其与表格进行比较?

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

这是我需要PRICE_LIST.ITEM_DESCRIPTION比较表:

--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表中的最后2个值将匹配,我要的是只此返回:

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

感谢您的帮助!

+0

你为什么要使用这样的设计很差的数据?你应该有一个主键,你可以用来匹配,而不是弥补格式错误的数据和草率的字符串解析和比较。您可能想要购买一本书或找到关于基本数据库设计原则的Web教程。 –

+0

似乎第一部分的描述可能对应于直径(.125 == 1/4等)。而且,是的,数据应该是结构化的。目前很难理解和使用。 – igr

+1

@KenWhite - 我不知道OP的具体情况。但是,您是否可以想象这种情况,即现有数据,在一个认识到他们以前的IT人员是多么愚蠢的组织中(只是看看数据模型),他们解雇了所有不熟练的人员,而是*雇佣OP和其他人处理混乱?当然,修复数据模型等等,你会怎么做?你不需要做**正确** OP的要求是什么?如果你需要帮助,你不会在这里问吗? – mathguy

回答

1

数据格式很糟糕。看来你需要创建一个自定义用户definied 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; 
/

,然后做就像这个例子:http://sqlfiddle.com/#!4/c7681/2

select p.*, evaluate_me(item_description) x 
from PRICE_LIST p; 

|   ITEM_DESCRIPTION | VENDOR_PARTNO |  X | 
|-----------------------------|---------------|--------| 
|   .374 x 3 w/ph KLT-6 |  5506125 | 1.122 | 
| .4375 x 3-1/2 w/ph KLT-3345 |  5506124 | 0.8125 | 
| .125 x 2-1/2 w/ph KLT-3211 |  5506123 | -0.25 | 
| .3125 x 4-1/2 w/ph KUR-44 |  5506127 | 0.75 | 

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 | 

这预计会极其缓慢,th将为左表的每一行调用e函数,然后调用右表的每一行。因此,如果左边的表格有10,000行,右边的表格有20000行(对RDBMS系统来说没有那么多),那么该函数将被称为10,000 + 10,000 * 20,000 = 200,010,000次。
这是一个糟糕的设计成本 - 数据不遵循First Normal Form的规则,必须在每次访问时解析。

为了使查询速度更快,你必须创建两个功能指标,否则当你启动这个查询,你可以参加每月休假:

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

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

感谢您花时间发布此信息。我明天会在办公室回来测试一下,然后回来。我同意这些数据是一团糟。它设计得很差,并且这种方式维持了15年。 – Delbudge

相关问题