从同一列中选择 N 个 MAX 和 MIN 值

时间:2021-05-12 16:37:08

标签: sql postgresql

我需要选择 n 个最高的人和 n 个最矮的人 人是男性。高度存储在名为“高度”的列中,性别存储在相应命名的列中(如 F 或 M)

enter image description here

我试过这样的事情

select name,height from people where gender = 'M' order by height asc limit 5

然后我想以某种方式将这个结果和同一行的结果按降序连接起来。

我也想知道你是否可以通过其他方式做到这一点。

我想象这个操作的结果是这样的

enter image description here

(身高数字是随机的,但左边的成对列应该包含最高的人,右边的成对列应该包含最短的)

我也试过这样的

(select name,height from people where gender = 'M' order by height desc limit 5) union (select name,height  from people where gender = 'M' order by height asc limit 5) order by height asc

但我不喜欢这样的结果,因为您没有将 2 列分隔为最短和最高,而是全部在 1 列中,您需要从顶部手动计算 n 人数量以查看哪一个是最高。

我在 postgreSQL 中这样做

1 个答案:

答案 0 :(得分:0)

假设两列没有重叠,您可以使用两个行号的技巧:

select max(name) filter (where seqnum_desc < seqnum_asc) as name_tall,
       max(height) filter (where seqnum_desc < seqnum_asc) as height_tall,
       max(name) filter (where seqnum_asc < seqnum_desc) as name_short,
       max(height) filter (where seqnum_asc < seqnum_desc) as height_short       
from (select p.*,
             row_number() over (partition by gender order by height asc) as seqnum_asc,
             row_number() over (partition by gender order by height desc) as seqnum_desc
      from people p
      where gender = 'M'
     ) p
where seqnum_asc <= 5 or seqnum_desc <= 5
group by least(seqnum_asc, seqnum_desc)

Here 是一个 db<>fiddle。

请注意:这应该适用于旧版本:

select max(case when seqnum_desc < seqnum_asc then name end) as name_tall,
       max(case when seqnum_desc < seqnum_asc then height end ) as height_tall,
       max(case when seqnum_asc < seqnum_desc then name end) as name_short,
       max(case when seqnum_asc < seqnum_desc then height end) as height_short       
from (select p.*,
             row_number() over (partition by gender order by height asc) as seqnum_asc,
             row_number() over (partition by gender order by height desc) as seqnum_desc
      from people p
      where gender = 'M'
     ) p
where seqnum_asc <= 5 or seqnum_desc <= 5
group by least(seqnum_asc, seqnum_desc)