2014-07-16 53 views
0

我正在查詢和使用oracle sql開發者真的很快提出了一個看法,幾乎幫助我做一些事情,我不知道該怎麼做。Oracle SQL Query在視圖上真的很慢但不是真正的表?

基本上我做了視圖,因爲我們的數據庫中的列不是必需的,在某些情況下,行是NULL或寫入不正確的註釋。這些行將包含「文本」列,其中會包含諸如「調整至銳步」帳戶等註釋。爲了正確運行我的查詢,我需要將每行都映射到'CUSTOMER_NO'值。

下面是這個視圖

SELECT t.*, 
CASE 
    WHEN LENGTH(CUSTOMER_NO) != '6' and text like '%Nike%' or CUSTOMER_NO IS NULL and text like '%Nike%' THEN 'NIK001' 
    WHEN LENGTH(CUSTOMER_NO) != '6' and text like '%Nike%' or CUSTOMER_NO IS NULL and text like '%Reebok%' THEN 'REB001' 
    ELSE CUSTOMER_NO 
    END as CUSTOMER_NO_ADJUSTED 
FROM 
gen_led_voucher_row_tab t 

所以這個觀點基本上都添加了一個新列「CUSTOMER_NO_ADJUSTED」,現在有一欄是100%填充。作品我預期的好。

但是,當我在這個視圖上運行我的原始查詢它只是繼續運行,並永遠不會結束/提取行。我讓它走了10分鐘,一無所獲。當我在表格上運行類似的查詢時,我會在30秒內得到數據。

下面是我試圖運行的查詢。我想基本上將CODE_D值分組爲一個部門名稱,並使用'EXISTS'選項運行查詢一次,以查看誰是現有客戶(在XXX個月內與我們做過業務),然後再以「NOT EXISTS」的形式運行它理論上只會產生新業務的部門價值(在指定月份內沒有與我們進行業務往來的客戶)。

SELECT 
/* CASE statement to rename CODE_D product lines to what the product is. List was provided by accounting in June of 2014 */ 

CASE 
     WHEN CODE_D = '11' or CODE_D = '12' or CODE_D = '18' or CODE_D IS NULL THEN 'Laces' 
    WHEN CODE_D = '15' or CODE_D = '16' or CODE_D = '40' or CODE_D = '45' or CODE_D = '50' 
     or CODE_D = '55' or CODE_D = '60' or CODE_D = '65' or CODE_D = '67' or CODE_D = '30' 
     or CODE_D = '35' THEN 'Custom Soles' 
    WHEN CODE_D = '17' THEN 'Custom Heels' 
    WHEN CODE_D = '19' or CODE_D = '39' or CODE_D = '49' or CODE_D = '59' or CODE_D = '69' 
     THEN 'Socks' 
    WHEN CODE_D = '14' THEN 'Sneakers' 
    WHEN CODE_D = '89' THEN 'Dress Shoes' 
    WHEN CODE_D = '99' THEN 'Other' 
    ELSE 'UNKNOWN' 
    END as DEPARTMENT, 
sum(coalesce(credit_amount, 0) - coalesce(debet_amount,0)) as TOTAL 
FROM 
KPIC_MIKE_METRIC1 a 
where ACCOUNTING_YEAR like '2014' 
and ACCOUNT not like '4010' 
and ACCOUNT like '4%' 



and Exists 
(
    Select * 
    From KPIC_MIKE_METRIC1 b 
    where voucher_date >= '01-FEB-13' 
    and  voucher_date < '01-FEB-14' 
    and ACCOUNT not like '4010' 
    and ACCOUNT like '4%' 
    and  (credit_amount > '1' or debet_amount > '1') 
    and  a.CUSTOMER_NO_ADJUSTED = b.CUSTOMER_NO_ADJUSTED 
) 



GROUP BY 
/* 
This GROUP BY statement needs to contain an entire copy of the CASE statement, minus the alias. 
If changes are made to the CASE statement please update this GROUP BY statement 
*/ 
CASE 
      WHEN CODE_D = '11' or CODE_D = '12' or CODE_D = '18' or CODE_D IS NULL THEN 'Laces' 
    WHEN CODE_D = '15' or CODE_D = '16' or CODE_D = '40' or CODE_D = '45' or CODE_D = '50' 
     or CODE_D = '55' or CODE_D = '60' or CODE_D = '65' or CODE_D = '67' or CODE_D = '30' 
     or CODE_D = '35' THEN 'Custom Soles' 
    WHEN CODE_D = '17' THEN 'Custom Heels' 
    WHEN CODE_D = '19' or CODE_D = '39' or CODE_D = '49' or CODE_D = '59' or CODE_D = '69' 
     THEN 'Socks' 
    WHEN CODE_D = '14' THEN 'Sneakers' 
    WHEN CODE_D = '89' THEN 'Dress Shoes' 
    WHEN CODE_D = '99' THEN 'Other' 
    ELSE 'UNKNOWN' 
    END 
ORDER BY TOTAL DESC 

任何幫助,將不勝感激。我是一個新手,我相信我可能會得到一些更好的建議,如何在這裏正確運行。任何幫助表示讚賞!

+0

什麼是執行計劃說什麼? –

回答

1

您從視圖KPIC_MIKE_METRIC1選擇,並且還對相同的觀點,在這裏你比較領域CUSTOMER_NO_ADJUSTED,這是你的計算字段,它由一個外殼與LIKE條件與在開始一個通配符並添加exists條款條件結束(因此不使用索引)。

如果此表包含很多行,那麼性能下降並不會讓我感到驚訝。

我會通過在表中存儲該信息來解決代碼到部門的映射。這至少使視圖更具可讀性和可維護性,並且您可以更輕鬆地添加代碼和部門。

對於性能,我可能會使用一個臨時表,但這主要是因爲我不像@mrjoltcola那樣具有確定性函數的經驗。 :)

+0

+1 - 實際上,將代碼映射到部門可能更有意義。根本不需要使用CASE語句。 – codenheim

+0

創建臨時表而不是視圖解決了所有問題!感謝您的解決方案!還要感謝@mrjoltcola的評論,他們非常有幫助! – Mike

1

我會做的第一件事是地址CUSTOMER_NO_ADJUSTED。您正在做大量工作來從case語句中生成計算列,然後將其用作JOIN列,這樣做根本無法執行。

您的目標應該是以某種方式將索引應用於該列上的聯接和條件,如果您要按照所顯示的方式使用它。

  1. 您可以將CASE邏輯封裝在DETERMINISTIC函數內的CUSTOMER_NO_ADJUSTED列的後面,然後在該函數上創建一個基於函數的索引。 DETERMINISTIC只是一種告訴Oracle的方式,對於相同的輸入,函數將始終返回相同的輸出。這樣,Oracle可以對其進行索引。如果沒有該關鍵字,Oracle將拒絕在其上創建基於功能的索引。
  2. 或者更傳統的方法 - 使CUSTOMER_NO_ADJUSTED成爲由INSERT或UPDATE觸發器填充的實際列,然後您可以使用簡單索引爲該列編制索引。

後者更直接直觀(便攜)。

更新:讀你的CASE語句後,我想你會得到更好的服務將其轉換爲部門查找表和DEPT_CODES

create table departments (
    id int primary key, 
    name varchar(50) 
); 

insert into departments values(1, 'Laces'); 
insert into departments values(2, 'Custom Soles'); 
insert into departments values(3, 'Custom Heels'); 
insert into departments values(4, 'Socks'); 

create table dept_codes (
    code_d varchar(2) primary key, 
    dept_id int 
); 

insert into dept_codes values('11', 1); -- Laces 
insert into dept_codes values('12', 1); 
insert into dept_codes values('18', 1); 
insert into dept_codes values('15', 2); -- Custom Soles 
insert into dept_codes values('16', 2); 
insert into dept_codes values('40', 2); 
insert into dept_codes values('45', 2); 
insert into dept_codes values('50', 2); 
insert into dept_codes values('17', 3); -- Custom Heels 
insert into dept_codes values('19', 4); -- Socks 
insert into dept_codes values('39', 4); 
+0

Wow @EvilTeach你在編輯我的文章時畫得很快,我剛剛失去了一個重要的編輯。 – codenheim

+0

有趣。抱歉。 – EvilTeach

+0

感謝您根據其他答案編輯答案。我真的不想創建任何表或添加任何列。我們的支持提供商對於違反與我們的支持協議的內容非常挑剔,我想做的最後一件事是給他們一個藉口,在需要時退出。我可能會嘗試這個臨時表。 – Mike