2013-08-29 29 views
0

我有這樣更換與左邊的WHERE JOIN或別的東西,聰明

SELECT * 
FROM 
table1, 
table2, 
table3, 
table4, 
table5, 
table6, 
table7, 
table8 
WHERE 
a = b and 
c = d and 
e = d and 
x1 = g and /*this is where x1 is changed into x2,x3,x4 or x5, labor intensive stuff*/ 
f = h and 
i = j 

問題的查詢是一些J的一些X1到X5僅工作等等,這取決於在一個變量一個名爲strfldvar的字段。我所知道的是,查詢適用於X1 = G只有當strfldvar = 'STR1'X2 = G只有當strfldvar = 'str2的'等等,所以我嘗試:

SELECT * 
FROM 
table1, 
table2, 
table3, 
table4, 
table5, 
table6, 
table7, 
table8 
WHERE 
a = b and 
c = d and 
e = d and 
(
(strfldvar = 'str1' AND x1 = g) 
OR (strfldvar = 'str2' AND x2 = g) 
OR (strfldvar = 'str3' AND x3 = g) 
OR (strfldvar = 'str4' AND x4 = g) 
OR (strfldvar = 'str5' AND x5 = g) 
) and 
f = h and 
i = j 

這需要永遠運行,並停止超時查詢。我想背後有一個笛卡爾產品,這使得這個如此複雜和耗時,所以顯然查詢有問題。我也嘗試過使用CASE THEN來關閉所有在WHERE之後無關的'=',並且給出了相同的結果。 我可以通過實現JOIN,LEFT JOIN,OUTER JOIN,INNER JOIN,UNION或其他東西來改變我的查詢對於strfldvar的所有情況快速進行此項工作還是沒有簡單的答案?每種類型的strfldvar的具體信息連接到table4到table8,str1類型的記錄的附加信息保存在table4中,而對於table8和str5以及其間的所有信息都是相同的。

我在做什麼錯在這裏?

+6

。 。如果你想解決這個問題,首先重寫查詢以將表別名放在所有列的前面,並使用正確的ANSI連接語法。你也可以解釋哪些表有哪些索引。 –

+1

請妥善縮進代碼,以便閱讀。而且,將所有內容放在自己的行中使得查詢冗長並且非常分散。 – usr

+1

要更深入地瞭解戈登的話,我建議閱讀[本文](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick- (Aaron Bertrand)(http://stackoverflow.com/users/61305/aaron-bertrand)的一系列不良習慣中,這些文章是針對SQL-Server的,但是許多適用於所有DBMS。但值得考慮的是,與ANSI 92顯式連接語法相比,使用ANSI 89 JOIN語法(隱式)時,Oracle *可以在某些事件中產生更好的計劃。 – GarethD

回答

1

您應該使用Inner連接而不是在整個表格中運行掃描。實際上,就你而言,你是從8表中選擇數據,然後在整個數據中進行掃描,這實際上並不是一項好技術。相反,你應該使用內部連接,它將在序列基礎上掃描你的結果,並使你的查詢相對快速。您的代碼看起來像

SELECT * FROM table1 Inner join table2 On table1.a=table2.b 
        Inner join table3 On table2.b=table2.c  

等..

+2

你真的低估了Oracle優化器。原始查詢應該與具有內部聯接的同等版本運行相同。 SQL是*描述性*語言,而不是*程序*語言。你描述了輸出應該是什麼樣的,優化器可以選擇不同的方式來實現這個目標。 –

+0

雖然我同意大多數人應該使用'ANSI 92 Join語法'是一個好主意,但是你的推理根本不是真的。 'SELECT * FROM a,b WHERE a.id = b.id'將生成[完全相同的執行計劃](http://sqlfiddle.com/#!4/f336b/1)作爲SELECT * FROM INNER加入b開b.ID = a。ID',它 不會像您假設在到達where子句之前掃描所有表。 – GarethD