2017-06-19 59 views
2

我正在將我的應用程序數據庫從oracle轉換爲postgres。我被困在一個通過語法連接的函數上。以下是Oracle查詢。如何將以下查詢從Oracle轉換爲Postgres進行連接?

PROCEDURE Get_Report_Data(parm_Billing_Month VARCHAR2, OUT Ref_Cur) IS 
BEGIN 
OPEN p_Data FOR 
    SELECT CASE 
      WHEN Id = 1 THEN 
      'Amount < 10000' 
      WHEN Id = 2 THEN 
      '10000-15000' 
      WHEN Id = 3 THEN 
      '15000-20000' 
      ELSE 
      'Amount > 20000' 
     END "Range", 
     SUM(Nvl(N1, 0)) N1, 
     SUM(Nvl(N2, 0)) N2, 
     SUM(Nvl(C1, 0)) C1, 
     SUM(Nvl(C2, 0)) C2, 
     SUM(Nvl(C3, 0)) C3, 
     SUM(Nvl(S1, 0)) S1, 
     SUM(Nvl(S2, 0)) S2, 
     COUNT(Site_Id) "No of Sites" 
    FROM (SELECT CASE 
        WHEN Nvl(Ed.Actual_Bill, 0) < 10000 THEN 
        1 
        WHEN Ed.Actual_Bill < 15000 THEN 
        2 
        WHEN Ed.Actual_Bill < 20000 THEN 
        3 
        ELSE 
        4 
       END Amount_Sort, 
       Decode(Er.Region_Id, 1, 1, 0) N1, 
       Decode(Er.Region_Id, 2, 1, 0) N2, 
       Decode(Er.Region_Id, 3, 1, 0) C1, 
       Decode(Er.Region_Id, 4, 1, 0) C2, 
       Decode(Er.Region_Id, 5, 1, 0) C3, 
       Decode(Er.Region_Id, 6, 1, 0) S1, 
       Decode(Er.Region_Id, 7, 1, 0) S2, 
       Ed.Site_Id 
      FROM Tbl_Details Ed, 
       Tbl_Site  Es, 
       Tbl_Region Er, 
       Tbl_Subregion Esr 
      WHERE Ed.Site_Id = Es.Site_Id 
      AND Es.Subregion_Id = Esr.Subregion_Id 
      AND Esr.Region_Id = Er.Region_Id 
      AND Ed.Billing_Month_f = parm_Billing_Month) Data, 
     (SELECT Regexp_Substr('1,2,3,4,', '[^,]+', 1, Rownum) Id 
      FROM Dual 
      CONNECT BY Rownum <= Length('1,2,3,4,') - 
        Length(REPLACE('1,2,3,4,', ','))) All_Value 
    WHERE Data.Amount_Sort(+) = All_Value.Id 
    GROUP BY All_Value.Id 
    ORDER BY AVG(All_Value.Id); 
END; 

當我將此查詢轉換爲postgres像Ref_Cur refcursor和NVL coalesce函數的一些變化。我仍然無法通過語法解決連接問題。有人建議使用CTE,但我無法得到它。任何幫助傢伙?

編輯 對於以下隨機谷歌搜索是對我的上述問題的答案。特別感謝MTO。

WHERE Ed.Site_Id = Es.Site_Id 
AND Es.Subregion_Id = Esr.Subregion_Id 
AND Esr.Region_Id = Er.Region_Id 
AND Ed.Billing_Month_f = p_Billing_Month) data 

Right Outer Join (Select 1 as Id union All 
        Select 2 as Id union All 
        Select 3 as Id union All 
        Select 4 as Id) all_value 
      On data.Amount_Sort = all_value.Id 
GROUP BY all_value.Id 
ORDER BY AVG(all_value.Id); 

回答

2

由於您的分層查詢似乎使用靜態字符串,可以轉換這樣的:

SELECT Regexp_Substr('1,2,3,4,', '[^,]+', 1, Rownum) Id 
FROM Dual 
CONNECT BY Rownum <= Length('1,2,3,4,') - Length(REPLACE('1,2,3,4,', ',') 

要:

SELECT 1 AS id FROM DUAL UNION ALL 
SELECT 2 FROM DUAL UNION ALL 
SELECT 3 FROM DUAL UNION ALL 
SELECT 4 FROM DUAL 

那麼這應該是簡單的轉換到PostgreSQL。

+2

非常感謝。非常好,簡單的答案。 –

3

可以在Postgres中簡化ID的「代」。

要麼使用values()條款:

Right Outer Join (values (1,2,3,4)) as all_value(id) On data.Amount_Sort = all_value.Id 

,或者,如果這些始終是一個連續號碼,使用generate_series()

Right Outer Join generate_series(1,4) as all_value(id) On data.Amount_Sort = all_value.Id 
+2

其實在我的下一個報告中,有一個複雜的查詢返回一些數字。所以簡單地說,我需要MTO提供的語法。但是非常感謝這些信息。 –

+0

@ Meta-Coder:我個人發現'values()'子語句更容易閱讀和維護,因爲複雜的'select .. union all select ...'語法 –

+2

我完全同意你的看法。即使在我的報告中,我也使用了值(1,2,3,4)子句,但在我的下一個報告中,我需要一個具有多個連接的複雜查詢。這讓我對Connect by的語法感到困惑。乾杯! –

相關問題