2016-12-12 87 views
0

我在PostgreSQL數據庫中有一個相當複雜的SQL語句,我在幾個視圖中使用它作爲基礎。但是在這個語句中,總和聚合函數被稱爲多次。我現在試圖通過使用一個變量多次刪除彙總這些值來優化這些視圖。PostgreSQL使用select語句中的值作爲該語句中的變量

我知道我可以使用@myvalue = 1,但這是在pgScript中,它不能在視圖中使用,因爲它是pgScript。

我已閱讀有關濫用配置設置來存儲變量,但我不知道這是如何玩視圖,我不喜歡這樣的黑客。

我想存儲在變量中的SQL部分是sum(v."Surface")::double precision,它重複多次。

如果有任何其他建議來優化這個SQL我完全贊成。

CREATE OR REPLACE VIEW mydb."MyTable" AS 
SELECT p."Id", 
    v."FunctionInt", 
    v."TypeInt", 
    sum(v."Surface") AS "SurfaceTotaal", 
    round((sum(v."Surface"::double precision * v."Average")/sum(v."Surface")::double precision)::numeric, 1) AS "Average", 
    round((sum(v."Surface"::double precision * v."E")/sum(v."Surface")::double precision)::numeric, 1) AS "E", 
    round((sum(v."Surface"::double precision * v."E1")/sum(v."Surface")::double precision)::numeric, 1) AS "E1", 
    round((sum(v."Surface"::double precision * v."E2")/sum(v."Surface")::double precision)::numeric, 1) AS "E2", 
    round((sum(v."Surface"::double precision * v."E3")/sum(v."Surface")::double precision)::numeric, 1) AS "E3", 
    round((sum(v."Surface"::double precision * v."M")/sum(v."Surface")::double precision)::numeric, 1) AS "M", 
    round((sum(v."Surface"::double precision * v."M1")/sum(v."Surface")::double precision)::numeric, 1) AS "M1", 
    round((sum(v."Surface"::double precision * v."M2")/sum(v."Surface")::double precision)::numeric, 1) AS "M2", 
    round((sum(v."Surface"::double precision * v."M3")/sum(v."Surface")::double precision)::numeric, 1) AS "M3", 
    round((sum(v."Surface"::double precision * v."G")/sum(v."Surface")::double precision)::numeric, 1) AS "G", 
    round((sum(v."Surface"::double precision * v."G1")/sum(v."Surface")::double precision)::numeric, 1) AS "G1", 
    round((sum(v."Surface"::double precision * v."G2")/sum(v."Surface")::double precision)::numeric, 1) AS "G2", 
    round((sum(v."Surface"::double precision * v."G3")/sum(v."Surface")::double precision)::numeric, 1) AS "G3", 
    round((sum(v."Surface"::double precision * v."G4")/sum(v."Surface")::double precision)::numeric, 1) AS "G4" 
FROM mydb."PTable" p, 
LATERAL ( 
    SELECT 
     v."Id", 
     v."Surface", 
     v."FunctionInt", 
     v."TypeInt", 
     r."YearGroupInt", 
     r."Average", 
     r."En" AS "E", 
     r."En1" AS "E1", 
     r."En2" AS "E2", 
     r."En3" AS "E3", 
     r."Mi" AS "M", 
     r."Mi1" AS "M1", 
     r."Mi2" AS "M2", 
     r."Mi3" AS "M3", 
     r."Gz" AS "G", 
     r."Gz1" AS "G1", 
     r."Gz2" AS "G2", 
     r."Gz3" AS "G3", 
     r."Gz4" AS "G4" 
    FROM mydb."VTable" v 
    JOIN mydb."RTable" r ON 
      v."FunctionInt" = r."FunctionInt" 
      AND v."TypeInt" = r."TypeInt" 
      AND v."YearGroupInt" = r."YearGroupInt" 
    WHERE v."PId" = p."Id") v 
GROUP BY p."Id", v."FunctionInt", v."TypeInt"; 
+0

'創建函數(var)返回表??.. –

+4

你不需要「優化」這個SQL。即使這個'sum(v。「Surface」)'在你的查詢中出現了1000次,優化器也足夠聰明,並且知道這是相同的值,並且只計算一次**,而不是1000次。 – krokodilko

+0

@krokodilko,我很希望能有這樣的事情,很好,這幾乎可以回答我的問題,除了我想要擺脫的衆多演員之外,還有其他建議嗎? –

回答

1

你的假設,即sum(v."Surface")::double precision計算多次不正確。計劃者處理這個問題,爲自己測試一下。

CREATE TABLE foo AS 
SELECT * FROM generate_series(1,1E7) AS t; 

然後..

EXPLAIN ANALYZE SELECT sum(t) FROM foo; 

現在,嘗試兩(沒有明顯減慢)

EXPLAIN ANALYZE SELECT sum(t), sum(t) FROM foo; 

計劃不折,雖然常量,

EXPLAIN ANALYZE SELECT sum(t), sum(t+0) FROM foo; 
+0

謝謝,還有其他建議嗎? –

+0

我永遠不會在其他地方用作其他視圖的基礎的視圖中放置聚合。規劃師不能在這裏推動WHERE條件。而且,另外。我也不會那樣做。如果他們需要雙精度,將它們存儲爲雙精度。保持它們的雙精度。如果您需要更多或更少的精度,請使用[數學函數](https://www.postgresql.org/docs/current/static/functions-math.html)。你對錶面的使用也告訴我你應該使用PostGIS或者立方體或者幾何體基類型。 –

+0

我同意,你誤解了我在多個視圖中使用的代碼,我沒有在另一個視圖中引用一個視圖(得出了同樣的結論,你說的是艱難的方式)。 Surface是存儲在我使用的數據庫中的integer類型的數據字段,因此它不是幾何類型 –