独立地对列进行排序,以便所有空值在每列最后
Sort columns independently, such that all nulls are last per column
这里有一个例子 table 叫做 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
我想把这个table中的空值移到最后。
我试过:
ORDER BY CASE name
WHEN 'fox' THEN fox
WHEN 'dog' THEN dog
END
但我不确定这是否真的是我想要的,虽然我可以做到,但 Postgres 一直在唠叨 fox 不是专栏 ORDER BY fox
。
也许我的方法完全是胡说八道,或者有某种合并魔法可以解决这个问题?
试试这样的东西:
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
您似乎认为 table 中会有“自然”顺序(如电子表格),但事实并非如此。如果没有 ORDER BY
,行将以 任意 顺序返回 - 这通常恰好与尚未更新的小 table 的输入顺序相同。
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
很重要,因为 'fox' 和 'dog' 的行数不同。
颜色按字母顺序排序,NULL
值在默认 ASCENDING
排序顺序中自动排在最后。参见:
- Sort by column ASC, but NULL values first?
这只扫描 table 一次。
您收到的错误消息的解释(“fox”不是列):
- PostgreSQL Where count condition
- GROUP BY + CASE statement
这里有一个例子 table 叫做 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
我想把这个table中的空值移到最后。 我试过:
ORDER BY CASE name
WHEN 'fox' THEN fox
WHEN 'dog' THEN dog
END
但我不确定这是否真的是我想要的,虽然我可以做到,但 Postgres 一直在唠叨 fox 不是专栏 ORDER BY fox
。
也许我的方法完全是胡说八道,或者有某种合并魔法可以解决这个问题?
试试这样的东西:
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
您似乎认为 table 中会有“自然”顺序(如电子表格),但事实并非如此。如果没有 ORDER BY
,行将以 任意 顺序返回 - 这通常恰好与尚未更新的小 table 的输入顺序相同。
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
很重要,因为 'fox' 和 'dog' 的行数不同。
颜色按字母顺序排序,NULL
值在默认 ASCENDING
排序顺序中自动排在最后。参见:
- Sort by column ASC, but NULL values first?
这只扫描 table 一次。
您收到的错误消息的解释(“fox”不是列):
- PostgreSQL Where count condition
- GROUP BY + CASE statement