使用CASE WHEN在postgresql中创建数据透视表的正确方法

moj*_*nes 6 sql postgresql pivot pivot-table case-when

我试图在postgresql中创建一个数据透视表类型视图,我差点就到了!这是基本查询:

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';
Run Code Online (Sandbox Code Playgroud)

而数据:

   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
Run Code Online (Sandbox Code Playgroud)

我想要得到的是以下内容:

acc      | species                  | phylum
AJ012531 | Paromalostomum fusculum  | Platyhelminthes
Run Code Online (Sandbox Code Playgroud)

我试着用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';
Run Code Online (Sandbox Code Playgroud)

这给了我输出:

   acc    |         species         |     phylum      
----------+-------------------------+-----------------
 AJ012531 | Paromalostomum fusculum | 
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | Platyhelminthes
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | 
 AJ012531 |                         | 
Run Code Online (Sandbox Code Playgroud)

现在我知道我必须在某个时候按照分组,所以我试试

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;
Run Code Online (Sandbox Code Playgroud)

但我害怕

ERROR:  column "tax_node.rank" must appear in the GROUP BY clause or be used in an aggregate function
Run Code Online (Sandbox Code Playgroud)

我之前能够找到的所有示例都使用了围绕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;
Run Code Online (Sandbox Code Playgroud)

但得到错误:

ERROR:  function first(character varying) does not exist
Run Code Online (Sandbox Code Playgroud)

任何人都可以提供任何提示吗?

Mat*_*ood 5

使用MAX()或MIN(),而不是FIRST().在这种情况下,每个组值的列中将包含所有NULL,除了最多只有一个非空值的值.根据定义,这是该组值的MIN和MAX(排除所有空值).