每列两列的前两行

时间:2015-02-24 22:22:09

标签: sql postgresql greatest-n-per-group window-functions

在PostgreSQL中给出这样的表:

Messages

message_id | creating_user_id | receiving_user_id | created_utc
-----------+------------------+-------------------+-------------
 1         | 1                | 2                 | 1424816011
 2         | 3                | 2                 | 1424816012
 3         | 3                | 2                 | 1424816013
 4         | 1                | 3                 | 1424816014
 5         | 1                | 3                 | 1424816015
 6         | 2                | 1                 | 1424816016
 7         | 2                | 1                 | 1424816017
 8         | 1                | 2                 | 1424816018

我希望每个creating_user_id / receiving_user_id获得最新的两行,其他user_id为1.因此查询的结果应如下所示:

message_id | creating_user_id | receiving_user_id | created_utc
-----------+------------------+-------------------+-------------
 1         | 1                | 2                 | 1424816011
 4         | 1                | 3                 | 1424816014
 5         | 1                | 3                 | 1424816015
 6         | 2                | 1                 | 1424816016

使用row_number()的窗口功能我可以为每个creating_user_id获取前2条消息,或为每个receiving_user_id获取前2条消息,但我不知道如何按creating_user_id / receiving_user_id获取前两条消息。

1 个答案:

答案 0 :(得分:1)

由于您过滤了其中一列为1(且不相关)的行,并且1恰好是所有列中的最小数量,因此您只需使用GREATEST(creating_user_id, receiving_user_id)来提取PARTITION BY相关的号码。 (否则你可以使用CASE。)

其余的是标准过程:在子查询中计算行号并在外部查询中选择前两个:

SELECT message_id, creating_user_id, receiving_user_id, created_utc
FROM (
   SELECT *
        , row_number() OVER (PARTITION BY GREATEST (creating_user_id
                                                  , receiving_user_id)
                             ORDER BY created_utc) AS rn
   FROM   messages
   WHERE  1 IN (creating_user_id, receiving_user_id)
   ) sub
WHERE  rn < 3
ORDER  BY created_utc;

完全是你的结果。

SQL Fiddle.

相关问题