2011-08-11 20 views
1

任何人有任何想法,爲什麼當我試圖運行此查詢時,它只是運行永遠不會停止??Oracle SQL - 左加2表不運行

「With」子句中的查詢自行運行正常。只是當我嘗試加入他們,我無法讓它正常運行?

--Process name and input 
With ProcessIn as 
(
select Data.Scan_time, equipment.equipment_desc, data.serial_number 

from Data, equipment 

where Data.equipment = equipment.equipm_barcode and data.quality_plan = 'N/A' and  data.error_code = 'N/A' 
) 

--Total process defects 
,ProcessDefect as 
(
select Data.Scan_time, equipment.equipment_desc, data.serial_number 

from Data, equipment 

where Data.equipment = equipment.equipm_barcode and (data.quality_plan <> 'N/A' or  data.error_code <> 'N/A') 
) 

Select concat(to_char(ProcessIn.SCAN_TIME, 'mm'), to_char(ProcessIn.SCAN_TIME, 'dd')) as "Date", ProcessIn.equipment_desc, count(ProcessIn.serial_number), count(ProcessDefect.serial_number) 

from ProcessIn 
Left Join ProcessDefect 
On concat(to_char(ProcessIn.SCAN_TIME, 'mm'),to_char(ProcessIn.SCAN_TIME, 'dd')) = concat(to_char(ProcessDefect.SCAN_TIME, 'mm'),to_char(ProcessDefect.SCAN_TIME, 'dd')) 
and ProcessIn.equipment_desc = ProcessDefect.equipment_desc 

group by concat(to_char(ProcessIn.SCAN_TIME, 'mm'), to_char(ProcessIn.SCAN_TIME, 'dd')), ProcessIn.equipment_desc 
; 

UPDATE 20110816 我用了一些建議,以改進我的查詢,但沒有成功。有人有其他建議嗎?此外,無論如何檢查我的索引是正確使用,因爲我是新的創建/使用它們。我只是使用Oracle接口來創建基於serial_number和smalldate的索引。

感謝

With ProcessIn as 
(
select data.smalldate, mip.mip_step_description, data.part_serial_number 

from Data, MIP 

where Data.equipment = MIP.equipment and data.quality_plan is null and data.error_code is null 
) 

,ProcessDefect as 
(
select data.smalldate, mip.mip_step_description, data.part_serial_number 

from Data, MIP 

where Data.equipment = MIP.equipment and (data.quality_plan is not null or data.error_code is not null) 
) 

Select ProcessIn.smalldate, ProcessIn.mip_step_description, count(ProcessIn.part_serial_number), count(ProcessDefect.part_serial_number) 

from ProcessIn 
Left Join ProcessDefect 
On ProcessIn.smalldate = ProcessDefect.smalldate 
and ProcessIn.mip_step_description = ProcessDefect.mip_step_description 

group by ProcessIn.smalldate, ProcessIn.mip_step_description 

UPDATE 110820

所以我已經取得一些進展,但需要幫助搞清楚最後一兩件事。我改變了查詢結構看現在這個樣子

select data.smalldate, mip.mip_step_description, error_code.error_code_en, count(case when (error_code is null and quality_plan is null) then data.part_serial_number end) as "Input", count(case when error_code is not null then data.part_serial_number end) as "Defects" 

from Data 

left join MIP 
On data.equipment = mip.equipment 

left join error_code 
on data.error_code = error_code.error_code_sn 

group by data.smalldate, mip.mip_step_description, error_code.error_code_en 

order by data.smalldate, mip.mip_step_description, count(data.part_serial_number) desc 

正如你可以看到在SELECT語句中,我使用的是在我的計數功能case語句。這工作正常。數據輸出像這樣

Date MIP_Desc Error_Code Input Defects 
1/1/2011 MIP Z (null)  100  0 
1/1/2011 MIP Z A   0  10 
1/1/2011 MIP Z B   0  15 

我想在輸入欄相同的輸入值,以填補整個具有相同的日期和MIP的所有行。

輸出應該是這樣的

Date MIP_Desc Error_Code Input Defects 
1/1/2011 MIP Z (null)  100  0 
1/1/2011 MIP Z A   100  10 
1/1/2011 MIP Z B   100  15 

任何提示?再次感謝您的幫助

+1

請張貼的查詢計劃。這很可能是因爲查詢確實非常昂貴,或者選擇了一個差的查詢計劃。 – Codo

+0

你的查詢結構的方式,查詢表涉及兩次查詢,並通過'equipment_desc'列加入,這個列不太可能被索引。難道不可能通過索引列加入,甚至更好,只涉及一次? – Codo

+0

偏離主題,但你應該停止使用隱含連接語法。這是一種SQL Antipattern和非常糟糕的編程技術。 – HLGEM

回答

1

我不是一個Oracle開發者,而是一個巨大的紅色標誌,我是你的JOIN語句兩側使用嵌套函數調用的:

On concat(to_char(ProcessIn.SCAN_TIME, 'mm'),to_char(ProcessIn.SCAN_TIME, 'dd')) = 
    concat(to_char(ProcessDefect.SCAN_TIME, 'mm'),to_char(ProcessDefect.SCAN_TIME, 'dd')) 

在SQL Server中,這是一個非常強大的指標,優化器在使用索引執行聯接操作時會遇到麻煩。如果您的子查詢生成大型記錄集,則JOIN可能需要很長時間才能完成。

如果您可以修改ON子句以不要求函數調用(如果可能的話,至少在一個上),它可能會幫助性能相當多。

+0

關於如何比較日期/時間列中沒有嵌套函數的日期和月份的任何想法? – AFJ

+0

除非你真的希望從比較中排除一年,否則你至少可以將它簡化爲'TRUNC(ProcessIn.SCAN_TIME)= TRUNC(ProcessDefect.SCAN_TIME)'。但是,這並不能使用索引。 – Codo

+0

你可以在CTE部分進行數據的收斂,然後連接可能會更好。在SQL Server中,我會在臨時表中執行此操作(包括轉換),然後對其進行索引,然後執行連接,但我不知道該選項在Oracle中是否可用。當然你可以按照你需要的方式存儲數據,那麼你只需要進行一次轉換。 – HLGEM

1

另一種方式來簡化此

的concat(TO_CHAR(ProcessIn.SCAN_TIME, '毫米'),TO_CHAR(ProcessIn.SCAN_TIME, 'DD'))= CONCAT(TO_CHAR(ProcessDefect.SCAN_TIME, '毫米') ,TO_CHAR(ProcessDefect.SCAN_TIME, 'DD'))

是說像

TO_CHAR(ProcessIn.SCAN_TIME, 'DDMM')= TO_CHAR(ProcessDefect.SCAN_TIME, 'DDMM')。

爲了提高性能,您可以創建基於功能的索引

在生產工程過程創建索引scan_time_idx(TO_CHAR(生產工程過程。SCAN_TIME,'ddmm'));

在ProcessIn上創建索引scan_time_idx(to_char(ProcessDefect.SCAN_TIME,'ddmm'));

有關基於函數的索引的更多信息,請參見http://www.akadia.com/services/ora_function_based_index_2.html

或者,您可以在to_char(tablename.SCAN_TIME,'ddmm')格式的'data'表中將scan_time存儲在名爲monthday的單獨列中,並索引新列。

製作完畢後,將查詢然後是這樣的: -

With ProcessIn as 
(
select Data.Scan_time, equipment.equipment_desc, data.serial_number,Data.monthday 

from Data, equipment 

where Data.equipment = equipment.equipm_barcode and data.quality_plan = 'N/A' and  data.error_code = 'N/A' 
) 

--Total process defects 
,ProcessDefect as 
(
select Data.Scan_time, equipment.equipment_desc, data.serial_number,Data.monthday 

from Data, equipment 

where Data.equipment = equipment.equipm_barcode and (data.quality_plan <> 'N/A' or   data.error_code <> 'N/A') 
) 

Select monthday as "Date", ProcessIn.equipment_desc,          count(ProcessIn.serial_number),  count(ProcessDefect.serial_number) 

from ProcessIn 
Left Join ProcessDefect 
On ProcessIn.monthday = ProcessDefect.monthday 
and ProcessIn.equipment_desc = ProcessDefect.equipment_desc 
group by ProcessIn.monthday, ProcessIn.equipment_desc 
; 
+0

由於'ProcessIn'和'ProcessDefect'是分解因子子查詢,而不是表格,因此您實際上需要'在數據上創建索引scan_time_idx(to_char(scan_time,'ddmm'))''。但我不認爲這會被用來執行這個查詢,因爲實際的表達式與索引表達式完全不匹配。 –

+0

啊是的,沒有注意到@Dave costa,我同意它應該是具有基於函數索引的表數據。不知道爲什麼它不會工作,只要連接更改爲to_char(ProcessIn.SCAN_TIME,'ddmm')= to_char(ProcessDefect.SCAN_TIME,'ddmm') –

+0

我試過你的簡單建議添加一個新的用to_char(tablename.SCAN_TIME,'ddmm')作爲測試,但不幸的是這似乎沒有多大幫助。 – AFJ