1

这是一个名为的示例表animal

name | color
------------
fox  | brown
fox  | red
dog  | gold

现在,我想要的是这个结果:

fox   | dog
-------------
brown | gold
red   | 

名称应该是结果的列,以不同的颜色值作为行。

我的第一个想法是:

SELECT color
FROM animal
WHERE name='fox'

[some sort of join?]

SELECT color 
FROM animal
WHERE name='dog'

但我不知道什么样的加入会奏效。

第二个想法:

SELECT CASE WHEN name = 'fox' THEN color ELSE NULL END AS fox,
CASE WHEN name = 'dog' THEN color ELSE NULL END AS dog
FROM animal

这将返回:

fox   | dog
-----------
red   | 
brown |
      | gold

我想将此表中的空值移到最后。我尝试过了:

ORDER BY CASE name
        WHEN 'fox' THEN fox
        WHEN 'dog' THEN dog
    END

但我不确定这是否真的是我想要的,Postgres 一直在唠叨说 fox 不是专栏,尽管我可以做到ORDER BY fox

也许我的方法完全是胡说八道,或者有某种合并魔法可以解决问题?

4

2 回答 2

1

您似乎认为表格中会有“自然”顺序(如电子表格中),但实际上没有。如果没有,则以任意ORDER BY顺序返回行- 这通常恰好与尚未更新的小表的输入顺序相同)。

WITH cte AS (
   SELECT row_number() OVER (PARTITION BY name ORDER BY color) AS rn, * 
   FROM   animal
   )
SELECT f.color AS fox, d.color AS dog
FROM        (SELECT rn, color FROM cte WHERE name = 'fox') f
FULL   JOIN (SELECT rn, color FROM cte WHERE name = 'dog') d USING (rn)
ORDER  BY rn;

要点

  • 在CTE中分别为每种动物的每种颜色附加序列号。
  • FULL [OUTER] JOIN是至关重要的,因为狐狸和狗的行数不同。
  • 颜色按字母顺序排序,NULL 值自动排在最后,因为它们是用FULL [OUTER] JOIN.
  • 这只扫描表一次

您收到的错误消息的解释(“fox”不是列):

于 2015-01-03T05:09:12.543 回答
0

尝试类似:

WITH fox_color as 
(SELECT color as fox, row_number() rn
 FROM animal
 WHERE name='fox'),
dog_color as 
(SELECT color as dog, row_number() rn
 FROM animal
 WHERE name='dog')
SELECT fox, dog
FROM fox_color 
JOIN dog_color ON fox_color.rn = dog_color.rn
于 2015-01-02T21:01:14.890 回答