PostgreSQL:在单个列上选择不同的值,同时在另一个列上进行排序

时间:2012-04-10 05:53:08

标签: sql postgresql distinct

我正在处理一个简单的消息数据库。

 id           | integer                     
 parent_id    | integer                     
 msg          | character varying(140)       
 create_dte   | numeric(10,0)

消息的parent_id为-1(顶级)或另一条消息的id。 我想返回最近的顶级消息 - 最近定义为 最近的父或其任何子女的create_dte。

这是我的问题:

select (case when parent_id != -1 then parent_id else id end) as mid, create_dte
from messages
order by create_dte desc

我的结果是这样的:

 mid  | create_dte 
------+----------------------
 5655 |           1333906651
 5462 |           1333816235
 5496 |           1333686356
 5157 |           1333685638
  676 |           1333648764
 5493 |           1333648630
  724 |           1333641318
 5402 |           1333470056
 5397 |           1333468897
 5396 |           1333468378
 3640 |           1333304212
 3434 |           1333300366
 2890 |           1333293369
 4958 |           1333288239
 4899 |           1333287641
 5203 |           1333287298
 4899 |           1333287275
 4899 |           1333285593

如何在保持create_dte类型的同时消除结果中的重复项? 我尝试过不同的,但总是失去排序。

这就是我需要的:

mid  | create_dte 
------+----------------------
 5655 |           1333906651
 5462 |           1333816235
 5496 |           1333686356
 5157 |           1333685638
  676 |           1333648764
 5493 |           1333648630
  724 |           1333641318
 5402 |           1333470056
 5397 |           1333468897
 5396 |           1333468378
 3640 |           1333304212
 3434 |           1333300366
 2890 |           1333293369
 4958 |           1333288239
 4899 |           1333287641
 5203 |           1333287298

(最后两行未返回4899已经出现在更新的create_dte的结果中。)

由于

2 个答案:

答案 0 :(得分:2)

尝试以下方法:

select (case when parent_id != -1 then parent_id else id end) as mid, max(create_dte )
from messages 
group by case when parent_id != -1 then parent_id else id end
order by max(create_dte) desc;

答案 1 :(得分:1)

除非我误解了你的问题,否则你需要遍历任何消息的整个层次结构,你需要一个递归查询来获取一个“root”消息id的所有消息。一旦你有了,那就是create_dte上的一个简单的max():

with msg_tree as (
    select id as root_id,
           id, 
           parent_id,
           create_dte
    from messages
    where parent_id = -1

    union all 

    select p.root_id,
           c.id,
           c.parent_id,
           c.create_dte
    from messages m 
        join msg_tree p on p.id = m.parent_id
)             
select root_id, 
       max(create_dte)
from msg_tree
group by root_id
order by 2;