每个两列组合的前两行

First two rows per combination of two columns

在 PostgreSQL 中给出这样的 table:

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

将 window 函数与 row_number() 结合使用,我可以获得每个 creating_user_id 的前 2 条消息或每个 receiving_user_id 的前 2 条消息,但我不确定如何获取每个 creating_user_id/receiving_user_id.

的前两条消息

由于您过滤了两列之一为 1(且不相关)的行,而 1 恰好是所有列中最小的数字,您可以简单地使用 GREATEST(creating_user_id, receiving_user_id) 来将 相关的 数字提炼为 PARTITION BY。 (否则你可以雇用 CASE。)

剩下的是标准程序:计算子查询中的行号和select外部查询中的前两个:

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.