2012-12-05 60 views
4

在我的項目上,數據模型發生了變化,我必須做一個新的請求來獲取信息,但過去它看起來像所有的數據都在同一行,但現在是該數據的一部分在另一個表中,它返回給我列。crosstab postgres - 行到列

所以我要求退貨:

http://www.hostingpics.net/viewer.php?id=724031request.jpg

我認爲這是很容易,但我真的不明白是怎麼功能crosstab作品。我嘗試這樣做:

SELECT * 
    FROM crosstab(
     'SELECT c.cd_type as typcou, c.dt_envoi as dtenvcou, c.commentaire as comment, c.signataire as signur 
      FROM comm.courrier c 
      WHERE c.id_formalite=1 
    order by 1,2', 
    'select lf.valeur as valeur from formalite.ligne_formalite lf, formalite.formalite f where lf.fk_formalite=f.id AND lf.fk_formalite=1' 
    ) 

AS c(typcou text, dtenvcou text, comment text, signataire text, valeur1 text, valeur2 text, valeur3 text); 

不過,我

ERREUR: 無效的返回類型SQL參謀部:42601 細節:查詢指定返回元組有7列,但交叉返回5

有人能幫我弄清楚有什麼問題嗎?

+0

你想要什麼(根據給定的截圖)幾乎是不可能的:你無法將一行的特定值與新列的值相匹配(你無法將第n個值設置爲n - 列)。 你應該製作一個特定的腳本來修改你的表模式。 –

+0

但是當我去幫助postgres時,他們說你可以使用交叉表來做這些 http://docs.postgresqlfr.org/9.0/tablefunc.html – user1879231

回答

0

我明白了! :

SELECT * 
FROM crosstab(
    'SELECT c.cd_type as typcou, c.dt_envoi as dtenvcou, c.commentaire as comment, c.signataire as signur, r.libelle, lf.valeur 
     FROM comm.courrier c, formalite.ligne_formalite lf, formalite.formalite f, norme.rubrique r 
     WHERE c.id_formalite=f.id AND lf.fk_formalite=f.id 
     AND c.id_formalite=1 AND r.id = lf.id_rubrique ORDER BY 1', 
     'SELECT DISTINCT libelle FROM norme.rubrique ORDER BY 1') 
AS (typcou char, dtenvcou text, comment text, signur text, codepost text, bureau text, date text); 
0

嘗試一些開源ETL工作室按優先順序排列:

  1. 了Talend
  2. Pentaho的
  3. 的JasperSoft

特別是如果你將要爲做到這一點往往大數據量,但我想知道,你真的應該使用Postgresql嗎?如果您願意,您也可以使用這些工具從一個數據庫服務器遷移到另一個數據庫服務器。

1

您沒有提到問題中的formalite.libelle列,這對解決方案很重要。

我建議爲您的主要查詢使用明確的JOIN語法 - 通常更易於閱讀和理解。

既然你無論如何都要拼出列定義列表中的所有列,它是更有效使用VALUES表達比SELECT DISTINCT ...crosstab()函數的第二個參數:

SELECT * 
FROM crosstab(
    'SELECT c.cd_type, c.dt_envoi, c.commentaire, c.signataire 
     , r.libelle, lf.valeur 
    FROM comm.courrier    c 
    JOIN formalite.formalite  f ON f.id = c.id_formalite 
    JOIN formalite.ligne_formalite lf ON lf.fk_formalite = f.id 
    JOIN norme.rubrique   r ON r.id = lf.id_rubrique 
    WHERE c.id_formalite = 1 
    ORDER BY 1' 

    ,$$VALUES ('codepost'::text), ('bureau'), ('date')$$ 
    ) 
AS (typcou char, dtenvcou text, comment text, signur text 
    , codepost text, bureau text, date text); 

More explanation and links in this closely related answer.

另外:我不會使用date作爲列名,它是SQL中的reserved word和PostgreSQL中的類型名。