2010-03-19 58 views
6

我想在postgresql中創建數據透視表類型視圖,並且差不多在那裏!這是基本的查詢:使用CASE在postgresql中創建數據透視表的正確方法WHERE

select 
acc2tax_node.acc, tax_node.name, tax_node.rank 
from 
tax_node, acc2tax_node 
where 
tax_node.taxid=acc2tax_node.taxid and acc2tax_node.acc='AJ012531'; 

而且數據:

acc |   name   |  rank  
----------+-------------------------+-------------- 
AJ012531 | Paromalostomum fusculum | species 
AJ012531 | Paromalostomum   | genus 
AJ012531 | Macrostomidae   | family 
AJ012531 | Macrostomida   | order 
AJ012531 | Macrostomorpha   | no rank 
AJ012531 | Turbellaria    | class 
AJ012531 | Platyhelminthes   | phylum 
AJ012531 | Acoelomata    | no rank 
AJ012531 | Bilateria    | no rank 
AJ012531 | Eumetazoa    | no rank 
AJ012531 | Metazoa     | kingdom 
AJ012531 | Fungi/Metazoa group  | no rank 
AJ012531 | Eukaryota    | superkingdom 
AJ012531 | cellular organisms  | no rank 

我想獲得如下:

acc  | species     | phylum 
AJ012531 | Paromalostomum fusculum | Platyhelminthes 

我試圖用CASE WHEN做到這一點,所以我有儘可能多的:

select 
acc2tax_node.acc, 
CASE tax_node.rank WHEN 'species' THEN tax_node.name ELSE NULL END as species, 
CASE tax_node.rank WHEN 'phylum' THEN tax_node.name ELSE NULL END as phylum 
from 
tax_node, acc2tax_node 
where 
tax_node.taxid=acc2tax_node.taxid and acc2tax_node.acc='AJ012531'; 

這使我的輸出:

acc |   species   |  phylum  
----------+-------------------------+----------------- 
AJ012531 | Paromalostomum fusculum | 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | Platyhelminthes 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | 
AJ012531 |       | 

現在我知道,我必須按在某些時候ACC,所以我儘量

select 
acc2tax_node.acc, 
CASE tax_node.rank WHEN 'species' THEN tax_node.name ELSE NULL END as sp, 
CASE tax_node.rank WHEN 'phylum' THEN tax_node.name ELSE NULL END as ph 
from 
tax_node, acc2tax_node 
where 
tax_node.taxid=acc2tax_node.taxid and acc2tax_node.acc='AJ012531' 
group by acc2tax_node.acc; 

,但我得到了可怕的

ERROR: column "tax_node.rank" must appear in the GROUP BY clause or be used in an aggregate function 

我之前找到的所有示例都使用了CASE語句中的SUM(),所以我猜這就是聚合函數。我一直在使用FIRST()嘗試:

select 
acc2tax_node.acc, 
FIRST(CASE tax_node.rank WHEN 'species' THEN tax_node.name ELSE NULL END) as sp, 
FIRST(CASE tax_node.rank WHEN 'phylum' THEN tax_node.name ELSE NULL END) as ph 
from tax_node, acc2tax_node where tax_node.taxid=acc2tax_node.taxid and acc2tax_node.acc='AJ012531' group by acc2tax_node.acc; 

,但得到的錯誤:

ERROR: function first(character varying) does not exist 

誰能提供任何提示?

+0

能否請您發佈此查詢的結果:' SELECT * FROM acc2tax_node WHERE acc ='AJ012531''? – Quassnoi 2010-03-19 13:04:53

回答

5

使用MAX()或MIN(),而不是FIRST()。在這種情況下,除了最多一個非空值之外,每個組中的值都會在列中包含所有NULL值。根據定義,這是該組值的最小值和最大值(所有的零值都被排除)。

+0

完美的作品,謝謝。出於某種原因,我認爲MAX()不起作用,因爲我使用的是字符串值。 – mojones 2010-03-19 15:18:27

0
SELECT atn.acc, ts.name AS species, tp.name AS phylum 
FROM acc2tax_node atn 
LEFT JOIN 
     tax_node ts 
ON  ts.taxid = atn.taxid 
     AND ts.rank = 'species' 
LEFT JOIN 
     tax_node tp 
ON  tp.taxid = atn.taxid 
     AND tp.rank = 'phylum' 
WHERE atn.acc = 'AJ012531 ' 
+0

請原諒我在格式化方面的可怕嘗試:-) – mojones 2010-03-19 12:51:44

0

的要求(在回覆中,而不是漂亮的格式化評論)進一步信息:

SELECT * FROM acc2tax_node WHERE acc = 'AJ012531'; 

    acc | taxid 
----------+-------- 
AJ012531 | 66400 
AJ012531 | 66399 
AJ012531 | 39216 
AJ012531 | 39215 
AJ012531 | 166235 
AJ012531 | 166384 
AJ012531 | 6157 
AJ012531 | 33214 
AJ012531 | 33213 
AJ012531 | 6072 
AJ012531 | 33208 
AJ012531 | 33154 
AJ012531 | 2759 
AJ012531 | 131567 
2

的PostgreSQL確實有支點查詢了幾個功能,請參閱本文的Postgresonline。您可以在contrib中找到這些功能。

+0

是的,我懷疑正確的做法是用scrosstab。我仍然想知道我在這裏爲自己的教育做錯了什麼。 – mojones 2010-03-19 14:21:19

0

執行:

SELECT report.* FROM crosstab(
select 
acc2tax_node.acc, tax_node.name, tax_node.rank 
from 
tax_node, acc2tax_node 
where 
tax_node.taxid=acc2tax_node.taxid and acc2tax_node.acc='AJ012531'; 
) AS report(species text, enus text, family text, ...) 
0

馬修伍德指出,使用MIN()或MAX(),而不是FIRST():

SELECT 
    an.acc, 
    MAX(
     CASE tn.rank 
      WHEN 'species' THEN tn.name 
      ELSE NULL 
     END 
    ) AS species, 
    MAX(
     CASE tn.rank 
      WHEN 'phylum' THEN tn.name 
      ELSE NULL 
     END 
    ) AS phylum 
FROM tax_node tn, 
    acc2tax_node an 
WHERE tn.taxid = an.taxid 
    and an.acc = 'AJ012531' 
GROUP by an.acc;