2017-11-18 9 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

相關問題