2011-07-08 84 views
0

運行Postres 7.4(是升級)複雜的查詢優化

這是一個視圖的查詢和它的使用了很多,但需要更長的時間比我想的。任何優化建議?隨着名稱的ID的任何字段建立索引

SELECT 
db_tbl_1.field_id, s."Field ID" AS foreign_field_id, 
s."Field Name" AS field_name, 
CASE  
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 3) = '01' THEN 'Field Label 1' 
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 4) = '321' THEN 'Field Label 1' 
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 5) = '1234' THEN 'Field Label 1' 
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 6) = '55555' THEN 'Field Label 1'  
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 3) = '76' THEN 'Field Label 2' 
END AS new_field, s.field_1, 
db_tbl_2.field_2, db_tbl_1.field_2_a, 
db_tbl_1.field_3, db_tbl_1.field_4, 
db_tbl_1.field_5, db_tbl_1.field_6, db_tbl_1.field_date_1, 
db_tbl_1.field_7, db_tbl_2.field_8 AS new_field_name, 
s."Field Date" AS field_date, db_tbl_1.created_date, 
CASE 
    WHEN (((DATE_TRUNC('month', "Field Date") + INTERVAL '2 MONTH') - "Field Date" > 60) AND 
     ((DATE_TRUNC('month', "Field Date") + INTERVAL '2 MONTH') - "Field Date" <= 92)) 
    THEN (DATE_TRUNC('month', "Field Date") + INTERVAL '2 MONTH') 
    -- the most days in a three month span can be 92 
    ELSE (DATE_TRUNC('month', "Field Date") + INTERVAL '3 MONTH') 
END AS next_date 
FROM db_schema_1.db_tbl_1, db_schema_1.db_tbl_2, "Table S" AS s 
WHERE db_tbl_1.program_level_id = db_tbl_2.id 
AND db_tbl_1.field_id = s."Another ID" 
AND (CASE 
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 3) = '01' THEN 1 
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 4) = '321' THEN 1 
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 5) = '1234' THEN 1 
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 6) = '55555' THEN 1 
    WHEN SUBSTRING(s."Field ID" FROM 0 FOR 3) = '76' THEN 1 
    ELSE 0 
END) = 1 
+0

不張貼作爲一個答案,因爲我不知道的Postgres,但在SQL Server中我儘量避免'SUBSTRING',而是在這樣的情況下使用'LEFT',因爲'LEFT'將使用索引和'SUBSTRING '不會。爲了得到那個'SUBSTRING',它可能評估每一行,並且只是做一個表掃描。 – JNK

+0

嗯,沒有找到與Postgres 7.4,或任何Postgres版本的LEFT()的文檔。你能提供一個參考嗎? –

+0

它顯然不在那裏!告訴你我不知道Postgres :) – JNK

回答

2

試圖改變過去的說法,你在哪裏使用case語句,因爲查詢將評估所有的人。然後檢查是否等於1,你應該嘗試和「OR」語句,因爲如果一個是正確的,它就不會評估其他的選擇。它應該會對你有所幫助。像這樣的東西。

AND (SUBSTRING(s."Field ID" FROM 0 FOR 3) = '01' OR 
    SUBSTRING(s."Field ID" FROM 0 FOR 4) = '321' OR 
    SUBSTRING(s."Field ID" FROM 0 FOR 5) = '1234' OR 
    SUBSTRING(s."Field ID" FROM 0 FOR 6) = '55555' OR 
    SUBSTRING(s."Field ID" FROM 0 FOR 3) = '76' 
) 
+0

謝謝,這確實有助於+1 –

+1

不知道postgres sql,但是如果有IN語句,你可以改變它SUBSTRING(s。「Field ID」FROM 0 FOR 3)IN('01','76' ),應該還有一點幫助 –

+0

以及IN與兩位數一起工作,但沒有/如果有任何優化或OR條件 –